diff options
author | Tristan Van Berkom <tristan.van.berkom@gmail.com> | 2004-11-18 06:25:34 +0000 |
---|---|---|
committer | David Hoover <dhoover@src.gnome.org> | 2004-11-18 06:25:34 +0000 |
commit | 2da412149f7eedd00bdb95577d2bba33fc933660 (patch) | |
tree | 503e30e50198e2869309b66bc895b1d6bf995813 | |
parent | e2ba2209d27f6fac052ffd9c676c9652221e5157 (diff) | |
download | glade-2da412149f7eedd00bdb95577d2bba33fc933660.tar.gz |
Replaced `GtkWidget *' with `GObject *' throughout the code
2004-11-16 Tristan Van Berkom <tristan.van.berkom@gmail.com>
* Replaced `GtkWidget *' with `GObject *' throughout the code
* Removed glade_util_get_parent and replaced with
glade_placeholder_get_parent or glade_widget_get_parent where
appropriate.
* Implemented a container abstraction layer which allows any object to
be a container through the xml catalog interface (GtkContainer is
handled implicitly).
* Straightened out a few crooked header files.
* Reworked loading a bit so that GladeProperties are loaded with the
values found in the xml file and that g_object_newv is called with
those values as well.
* Deprecated / Removed useless pre_create functions, anything that was
a pre_create is now done in post create without any regression.
* glade_gtk_container_fill_empty now checks if there are existing
children before adding one.
* Added comment on how to fix glade-project-view
* Half implemented addition of non-widget children in glade-popup.c
* glade-utils "nodes" code now also serves as a selection marker for
any non-widget objects (widgets are still handled by drawing
selections). Also reverted my change to queue_draw_nodes... seems to
work for now.
* For now I removed the unused notion of "grand-child" packing
properties (that will have to be inspected and implemented properly
if need be).
* updated XML files accordingly.
39 files changed, 1934 insertions, 1091 deletions
@@ -1,3 +1,42 @@ +2004-11-16 Tristan Van Berkom <tristan.van.berkom@gmail.com> + + * Replaced `GtkWidget *' with `GObject *' throughout the code + + * Removed glade_util_get_parent and replaced with + glade_placeholder_get_parent or glade_widget_get_parent where + appropriate. + + * Implemented a container abstraction layer which allows any object to + be a container through the xml catalog interface (GtkContainer is + handled implicitly). + + * Straightened out a few crooked header files. + + * Reworked loading a bit so that GladeProperties are loaded with the + values found in the xml file and that g_object_newv is called with + those values as well. + + * Deprecated / Removed useless pre_create functions, anything that was + a pre_create is now done in post create without any regression. + + * glade_gtk_container_fill_empty now checks if there are existing + children before adding one. + + * Added comment on how to fix glade-project-view + + * Half implemented addition of non-widget children in glade-popup.c + + * glade-utils "nodes" code now also serves as a selection marker for + any non-widget objects (widgets are still handled by drawing + selections). Also reverted my change to queue_draw_nodes... seems to + work for now. + + * For now I removed the unused notion of "grand-child" packing + properties (that will have to be inspected and implemented properly + if need be). + + * updated XML files accordingly. + 2004-11-17 Ivan Wong <email@ivanwong.info> * configure.in: diff --git a/src/glade-command.c b/src/glade-command.c index 7ff4d95d..229be361 100644 --- a/src/glade-command.c +++ b/src/glade-command.c @@ -570,17 +570,19 @@ glade_command_create_delete_undo (GladeCommand *cmd) static gboolean glade_command_create_execute (GladeCommandCreateDelete *me) { - GladeWidget *widget = me->widget; + GladeWidget *widget = me->widget; GladePlaceholder *placeholder = me->placeholder; - if (!GTK_WIDGET_TOPLEVEL (widget->widget)) - glade_widget_replace (GTK_WIDGET (placeholder), widget->widget); + if (!GTK_WIDGET_TOPLEVEL (widget->object)) + glade_widget_replace + (glade_placeholder_get_parent (placeholder), + G_OBJECT (placeholder), widget->object); - glade_project_add_widget (widget->project, widget->widget); - glade_project_selection_set (widget->project, widget->widget, TRUE); + glade_project_add_object (widget->project, widget->object); + glade_project_selection_set (widget->project, widget->object, TRUE); - if (GTK_IS_WIDGET (widget->widget)) - gtk_widget_show_all (widget->widget); + if (GTK_IS_WIDGET (widget->object)) + gtk_widget_show_all (GTK_WIDGET (widget->object)); return TRUE; } @@ -602,12 +604,15 @@ glade_command_delete_execute (GladeCommandCreateDelete *me) g_object_ref (G_OBJECT (me->placeholder)); } - glade_widget_replace (widget->widget, GTK_WIDGET (me->placeholder)); + glade_widget_replace + (glade_widget_get_parent (widget), + widget->object, G_OBJECT (me->placeholder)); } - gtk_widget_hide (widget->widget); + if (GTK_IS_WIDGET (widget->object)) + gtk_widget_hide (GTK_WIDGET (widget->object)); - glade_project_remove_widget (widget->project, widget->widget); + glade_project_remove_object (widget->project, widget->object); return TRUE; } @@ -641,7 +646,9 @@ glade_command_create_delete_finalize (GObject *obj) cmd = GLADE_COMMAND_CREATE_DELETE (obj); - g_object_unref (cmd->placeholder); + if (cmd->placeholder) + g_object_unref (cmd->placeholder); + g_object_unref (cmd->widget); glade_command_finalize (obj); @@ -734,12 +741,13 @@ glade_command_create (GladeWidgetClass *class, gpw = glade_project_window_get (); g_return_if_fail (GLADE_IS_PALETTE (gpw->palette)); - if (placeholder) + /* AFAIK Only GtkWindow and derivaitves can be toplevels. */ + if (g_type_is_a (class->type, GTK_TYPE_WINDOW) == FALSE) { - parent = glade_util_get_parent (GTK_WIDGET (placeholder)); + parent = glade_placeholder_get_parent (placeholder); g_return_if_fail (parent != NULL); } - + if (!project) project = parent->project; @@ -794,20 +802,22 @@ glade_command_paste_execute (GladeCommandCutCopyPaste *me) g_return_val_if_fail (g_list_find (me->clipboard->widgets, glade_widget), TRUE); - parent = glade_util_get_parent (GTK_WIDGET (placeholder)); + parent = glade_placeholder_get_parent (placeholder); project = parent->project; - if (!GTK_WIDGET_TOPLEVEL (glade_widget->widget)) + if (!GTK_WIDGET_TOPLEVEL (glade_widget->object)) { g_object_ref (G_OBJECT (placeholder)); - glade_widget_replace (GTK_WIDGET (placeholder), glade_widget->widget); + glade_widget_replace + (glade_placeholder_get_parent (placeholder), + G_OBJECT (placeholder), glade_widget->object); } - glade_project_add_widget (project, glade_widget->widget); - glade_project_selection_set (glade_widget->project, glade_widget->widget, TRUE); + glade_project_add_object (project, glade_widget->object); + glade_project_selection_set (glade_widget->project, glade_widget->object, TRUE); - if (GTK_IS_WIDGET (glade_widget->widget)) - gtk_widget_show_all (GTK_WIDGET (glade_widget->widget)); + if (GTK_IS_WIDGET (glade_widget->object)) + gtk_widget_show_all (GTK_WIDGET (glade_widget->object)); glade_clipboard_remove (me->clipboard, glade_widget); @@ -831,12 +841,15 @@ glade_command_cut_execute (GladeCommandCutCopyPaste *me) g_object_ref (G_OBJECT (me->placeholder)); } - glade_widget_replace (glade_widget->widget, GTK_WIDGET (me->placeholder)); + glade_widget_replace + (glade_widget_get_parent (glade_widget), + glade_widget->object, G_OBJECT (me->placeholder)); } - gtk_widget_hide (glade_widget->widget); + if (GTK_IS_WIDGET (glade_widget->object)) + gtk_widget_hide (GTK_WIDGET (glade_widget->object)); - glade_project_remove_widget (glade_widget->project, glade_widget->widget); + glade_project_remove_object (glade_widget->project, glade_widget->object); return TRUE; } @@ -1003,7 +1016,7 @@ glade_command_paste (GladePlaceholder *placeholder) if (widget == NULL) return; - parent = glade_util_get_parent (GTK_WIDGET (placeholder)); + parent = glade_placeholder_get_parent (placeholder); glade_command_cut_copy_paste_common (widget, placeholder, parent->project, GLADE_PASTE); } diff --git a/src/glade-editor.c b/src/glade-editor.c index de48490e..063b9d90 100644 --- a/src/glade-editor.c +++ b/src/glade-editor.c @@ -203,7 +203,7 @@ glade_editor_widget_name_changed (GtkWidget *editable, GladeEditor *editor) if (editor->loading) return; - g_return_if_fail (GTK_IS_WIDGET (editor->loaded_widget->widget)); + g_return_if_fail (GTK_IS_WIDGET (editor->loaded_widget->object)); widget = editor->loaded_widget; new_name = gtk_editable_get_chars (GTK_EDITABLE (editable), 0, -1); @@ -1015,7 +1015,7 @@ glade_editor_on_edit_menu_click (GtkButton *button, GladeEditor *editor) g_return_if_fail (GLADE_IS_EDITOR (editor)); g_return_if_fail (editor->loaded_widget != NULL); - menubar = editor->loaded_widget->widget; + menubar = GTK_WIDGET(editor->loaded_widget->object); g_return_if_fail (GTK_IS_MENU_BAR (menubar)); project = editor->loaded_widget->project; @@ -1219,7 +1219,7 @@ static void glade_editor_property_load_integer (GladeEditorProperty *property) { GtkWidget *spin = NULL; - gfloat val; + gfloat val = 0.0F; g_return_if_fail (property != NULL); g_return_if_fail (property->property != NULL); @@ -1483,13 +1483,13 @@ glade_editor_load_packing_page (GladeEditor *editor, GladeWidget *widget) { static GladeEditorTable *old = NULL; static GList *old_props = NULL; + GladeEditorProperty *editor_property; - GladeEditorTable *table; - GladePropertyClass *property_class; - GladeWidget *parent; - GladeWidget *ancestor; - GtkContainer *container; - GList *list, *children; + GladeEditorTable *table; + GladeProperty *property; + GladeWidget *parent; + GtkContainer *container; + GList *list, *children; /* Remove the old properties */ container = GTK_CONTAINER (editor->vbox_packing); @@ -1513,29 +1513,21 @@ glade_editor_load_packing_page (GladeEditor *editor, GladeWidget *widget) return; /* if the widget is a toplevel there are no packing properties */ - parent = glade_widget_get_parent (widget); - if (!parent) + if ((parent = glade_widget_get_parent (widget)) == NULL) return; /* Now add the new properties */ table = glade_editor_table_new (); table->editor = editor; table->type = TABLE_TYPE_PACKING; - - for (ancestor = parent; ancestor != NULL; ancestor = glade_widget_get_parent (ancestor)) + + for (list = widget->packing_properties; list && list->data; list = list->next) { - for (list = ancestor->widget_class->child_properties; list; list = list->next) - { - property_class = list->data; - if (!ancestor->widget_class->child_property_applies - (ancestor->widget, widget->widget, property_class->id)) - continue; - - g_assert (property_class->packing == TRUE); - editor_property = glade_editor_table_append_item (table, property_class); - old_props = g_list_prepend (old_props, editor_property); - glade_editor_property_load (editor_property, widget); - } + property = list->data; + g_assert (property->class->packing == TRUE); + editor_property = glade_editor_table_append_item (table, property->class); + old_props = g_list_prepend (old_props, editor_property); + glade_editor_property_load (editor_property, widget); } gtk_widget_show_all (table->table_widget); @@ -1628,7 +1620,7 @@ glade_editor_add_signal (GladeEditor *editor, signal_name = g_signal_name (signal_id); widget_name = glade_widget_get_name (editor->loaded_widget); - widget_type = glade_widget_class_get_type (glade_widget_get_class (editor->loaded_widget)); + widget_type = editor->loaded_widget->widget_class->type; g_signal_emit (G_OBJECT (editor), glade_editor_signals [ADD_SIGNAL], 0, @@ -1675,3 +1667,24 @@ glade_editor_query_popup (GladeEditor *editor, GladeWidget *widget) gtk_widget_destroy (dialog); } + + +gboolean +glade_editor_editable_property (GParamSpec *pspec) +{ + g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE); + return + (G_IS_PARAM_SPEC_ENUM(pspec) || + G_IS_PARAM_SPEC_FLAGS(pspec) || + G_IS_PARAM_SPEC_STRING(pspec) || + G_IS_PARAM_SPEC_BOOLEAN(pspec) || + G_IS_PARAM_SPEC_FLOAT(pspec) || + G_IS_PARAM_SPEC_DOUBLE(pspec) || + G_IS_PARAM_SPEC_INT(pspec) || + G_IS_PARAM_SPEC_UINT(pspec) || + G_IS_PARAM_SPEC_LONG(pspec) || + G_IS_PARAM_SPEC_ULONG(pspec) || + G_IS_PARAM_SPEC_INT64(pspec) || + G_IS_PARAM_SPEC_UINT64(pspec) || + G_IS_PARAM_SPEC_UNICHAR(pspec)) ? TRUE : FALSE; +} diff --git a/src/glade-editor.h b/src/glade-editor.h index 886deed0..40d4d607 100644 --- a/src/glade-editor.h +++ b/src/glade-editor.h @@ -191,11 +191,15 @@ GType glade_editor_get_type (void); GladeEditor *glade_editor_new (void); -void glade_editor_load_widget (GladeEditor *editor, GladeWidget *widget); -void glade_editor_add_signal (GladeEditor *editor, guint id_signal, const char *callback_name); -void glade_editor_update_widget_name (GladeEditor *editor); -void glade_editor_query_popup (GladeEditor *editor, GladeWidget *widget); - +void glade_editor_load_widget (GladeEditor *editor, + GladeWidget *widget); +void glade_editor_add_signal (GladeEditor *editor, + guint id_signal, + const char *callback_name); +void glade_editor_update_widget_name (GladeEditor *editor); +void glade_editor_query_popup (GladeEditor *editor, + GladeWidget *widget); +gboolean glade_editor_editable_property (GParamSpec *pspec); G_END_DECLS diff --git a/src/glade-gtk.c b/src/glade-gtk.c index 863a31be..30fd99ed 100644 --- a/src/glade-gtk.c +++ b/src/glade-gtk.c @@ -207,7 +207,7 @@ glade_gtk_widget_condition (GladeWidgetClass *klass) void GLADEGTK_API glade_gtk_widget_set_tooltip (GObject *object, GValue *value) { - GladeWidget *glade_widget = glade_widget_get_from_gtk_widget (GTK_WIDGET (object)); + GladeWidget *glade_widget = glade_widget_get_from_gobject (GTK_WIDGET (object)); GladeProject *project = glade_widget_get_project (glade_widget); GtkTooltips *tooltips = glade_project_get_tooltips (project); const char *tooltip; @@ -375,7 +375,7 @@ glade_gtk_box_get_first_blank (GtkBox *box) { GtkWidget *widget = ((GtkBoxChild *) (child->data))->widget; - if ((gwidget = glade_widget_get_from_gtk_widget (widget)) != NULL) + if ((gwidget = glade_widget_get_from_gobject (widget)) != NULL) { gint gwidget_position; GladeProperty *property = @@ -430,7 +430,7 @@ glade_gtk_box_set_size (GObject *object, GValue *value) { GtkWidget *child_widget = ((GtkBoxChild *) (child->data))->widget; - if (glade_widget_get_from_gtk_widget (child_widget)) + if (glade_widget_get_from_gobject (child_widget)) /* In this case, refuse to shrink */ break; @@ -451,7 +451,7 @@ glade_gtk_box_verify_size (GObject *object, GValue *value) child = g_list_previous (child), old_size--) { GtkWidget *widget = ((GtkBoxChild *) (child->data))->widget; - if (glade_widget_get_from_gtk_widget (widget) != NULL) + if (glade_widget_get_from_gobject (widget) != NULL) /* In this case, refuse to shrink */ return FALSE; } @@ -507,7 +507,7 @@ glade_gtk_toolbar_set_size (GObject *object, GValue *value) { GtkWidget *child_widget = ((GtkToolbarChild *) child->data)->widget; - if (glade_widget_get_from_gtk_widget (child_widget)) + if (glade_widget_get_from_gobject (child_widget)) break; gtk_container_remove (GTK_CONTAINER (toolbar), child_widget); @@ -531,7 +531,7 @@ glade_gtk_toolbar_verify_size (GObject *object, GValue *value) { GtkWidget *child_widget = ((GtkToolbarChild *) child->data)->widget; - if (glade_widget_get_from_gtk_widget (child_widget)) + if (glade_widget_get_from_gobject (child_widget)) return FALSE; } return TRUE; @@ -611,7 +611,7 @@ glade_gtk_notebook_get_first_blank_page (GtkNotebook *notebook) for (position = 0; position < gtk_notebook_get_n_pages (notebook); position++) { widget = gtk_notebook_get_nth_page (notebook, position); - if ((gwidget = glade_widget_get_from_gtk_widget (widget)) != NULL) + if ((gwidget = glade_widget_get_from_gobject (widget)) != NULL) { GladeProperty *property = glade_widget_get_property (gwidget, "position"); @@ -643,7 +643,7 @@ glade_gtk_notebook_set_n_pages (GObject *object, GValue *value) notebook = GTK_NOTEBOOK (object); g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); - widget = glade_widget_get_from_gtk_widget (GTK_WIDGET (notebook)); + widget = glade_widget_get_from_gobject (GTK_WIDGET (notebook)); g_return_if_fail (widget != NULL); new_size = g_value_get_int (value); @@ -672,7 +672,7 @@ glade_gtk_notebook_set_n_pages (GObject *object, GValue *value) * If we got it, and its not a placeholder, remove it * from project. */ - if (glade_widget_get_from_gtk_widget (child_widget)) + if (glade_widget_get_from_gobject (child_widget)) break; gtk_notebook_remove_page (notebook, old_size-1); @@ -696,7 +696,7 @@ glade_gtk_notebook_verify_n_pages (GObject *object, GValue *value) * If we got it, and its not a placeholder, remove it * from project. */ - if (glade_widget_get_from_gtk_widget (child_widget)) + if (glade_widget_get_from_gobject (child_widget)) return FALSE; } return TRUE; @@ -771,7 +771,7 @@ glade_gtk_table_set_n_common (GObject *object, GValue *value, gboolean for_rows) /* Refuse to shrink if it means orphaning widgets */ return; - widget = glade_widget_get_from_gtk_widget (GTK_WIDGET (table)); + widget = glade_widget_get_from_gobject (GTK_WIDGET (table)); g_return_if_fail (widget != NULL); if (for_rows) @@ -909,7 +909,7 @@ glade_gtk_button_set_stock (GObject *object, GValue *value) button = GTK_WIDGET (object); g_return_if_fail (GTK_IS_BUTTON (button)); - glade_widget = glade_widget_get_from_gtk_widget (button); + glade_widget = glade_widget_get_from_gobject (button); g_return_if_fail (glade_widget != NULL); property = glade_widget_get_property (glade_widget, "stock"); @@ -1034,40 +1034,6 @@ ignore (GObject *object, GValue *value) } -/* -------------------------- Pre Create functions -------------------------- */ -/* a GtkTable starts with a default size of 1x1, and setter/getter of - * rows/columns expect * the GtkTable to hold this number of placeholders, so - * we should add it - */ - -/** - * glade_gtk_tree_pre_create: - * @object: - * - * TODO: write me - */ -void GLADEGTK_API -glade_gtk_tree_view_pre_create (GObject *object) -{ - GtkWidget *tree_view = GTK_WIDGET (object); - GtkTreeStore *store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_STRING); - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - - gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (store)); - g_object_unref (G_OBJECT (store)); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes - ("Column 1", renderer, "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes - ("Column 2", renderer, "text", 1, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); -} - /* ------------------------- Post Create functions ------------------------- */ static gboolean glade_gtk_fixed_button_press (GtkWidget *widget, @@ -1103,7 +1069,7 @@ glade_gtk_fixed_button_press (GtkWidget *widget, (glade_project_window_get_active_project(gpw)); new_widget = GTK_WIDGET(selection->data); - new_gwidget = glade_widget_get_from_gtk_widget(new_widget); + new_gwidget = glade_widget_get_from_gobject(new_widget); g_value_init (&value, G_TYPE_INT); @@ -1197,7 +1163,7 @@ glade_gtk_dialog_post_create (GObject *object) g_return_if_fail (GTK_IS_DIALOG (dialog)); - widget = glade_widget_get_from_gtk_widget (GTK_WIDGET (dialog)); + widget = glade_widget_get_from_gobject (GTK_WIDGET (dialog)); if (!widget) return; @@ -1206,7 +1172,8 @@ glade_gtk_dialog_post_create (GObject *object) if (!child_class) return; - vbox_widget = glade_widget_new_for_internal_child (child_class, widget, dialog->vbox, "vbox"); + vbox_widget = glade_widget_new_for_internal_child (child_class, widget, + G_OBJECT(dialog->vbox), "vbox"); if (!vbox_widget) return; @@ -1221,7 +1188,7 @@ glade_gtk_dialog_post_create (GObject *object) actionarea_widget = glade_widget_new_for_internal_child - (child_class, vbox_widget, dialog->action_area, "action_area"); + (child_class, vbox_widget, G_OBJECT(dialog->action_area), "action_area"); if (!actionarea_widget) return; @@ -1247,7 +1214,7 @@ glade_gtk_message_dialog_post_create (GObject *object) g_return_if_fail (GTK_IS_MESSAGE_DIALOG (dialog)); - widget = glade_widget_get_from_gtk_widget (GTK_WIDGET (dialog)); + widget = glade_widget_get_from_gobject (GTK_WIDGET (dialog)); if (!widget) return; @@ -1258,7 +1225,7 @@ glade_gtk_message_dialog_post_create (GObject *object) return; vbox_widget = glade_widget_new_for_internal_child (child_class, widget, - dialog->vbox, "vbox"); + G_OBJECT(dialog->vbox), "vbox"); if (!vbox_widget) return; @@ -1268,7 +1235,7 @@ glade_gtk_message_dialog_post_create (GObject *object) actionarea_widget = glade_widget_new_for_internal_child - (child_class, vbox_widget, dialog->action_area, "action_area"); + (child_class, vbox_widget, G_OBJECT(dialog->action_area), "action_area"); if (!actionarea_widget) return; @@ -1276,6 +1243,33 @@ glade_gtk_message_dialog_post_create (GObject *object) gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 115); } +/** + * glade_gtk_tree_post_create: + * @object: + * + * TODO: write me + */ +void GLADEGTK_API +glade_gtk_tree_view_post_create (GObject *object) +{ + GtkWidget *tree_view = GTK_WIDGET (object); + GtkTreeStore *store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_STRING); + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (store)); + g_object_unref (G_OBJECT (store)); + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes + ("Column 1", renderer, "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes + ("Column 2", renderer, "text", 1, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); +} /* ------------------------ Replace child functions ------------------------ */ /** @@ -1287,9 +1281,9 @@ glade_gtk_message_dialog_post_create (GObject *object) * TODO: write me */ void GLADEGTK_API -glade_gtk_container_replace_child (GtkWidget *current, - GtkWidget *new, - GtkWidget *container) +glade_gtk_container_replace_child (GtkWidget *container, + GtkWidget *current, + GtkWidget *new) { GParamSpec **param_spec; GValue *value; @@ -1333,9 +1327,9 @@ glade_gtk_container_replace_child (GtkWidget *current, * TODO: write me */ void GLADEGTK_API -glade_gtk_notebook_replace_child (GtkWidget *current, - GtkWidget *new, - GtkWidget *container) +glade_gtk_notebook_replace_child (GtkWidget *container, + GtkWidget *current, + GtkWidget *new) { GtkNotebook *notebook; GtkWidget *page; @@ -1384,9 +1378,13 @@ glade_gtk_notebook_replace_child (GtkWidget *current, void GLADEGTK_API glade_gtk_container_fill_empty (GObject *container) { + GList *children; g_return_if_fail (GTK_IS_CONTAINER (container)); - - gtk_container_add (GTK_CONTAINER (container), glade_placeholder_new ()); + + if ((children = gtk_container_get_children (GTK_CONTAINER (container))) == NULL) + gtk_container_add (GTK_CONTAINER (container), glade_placeholder_new ()); + else + g_list_free (children); } /** diff --git a/src/glade-placeholder.c b/src/glade-placeholder.c index e94b713d..32e520f8 100644 --- a/src/glade-placeholder.c +++ b/src/glade-placeholder.c @@ -248,9 +248,8 @@ static GladeProject* glade_placeholder_get_project (GladePlaceholder *placeholder) { GladeWidget *parent; - - parent = glade_util_get_parent (GTK_WIDGET (placeholder)); - return parent->project; + parent = glade_placeholder_get_parent (placeholder); + return parent ? parent->project : NULL; } static gboolean @@ -320,7 +319,7 @@ glade_placeholder_button_press (GtkWidget *widget, GdkEventButton *event) GladeProject *project; project = glade_placeholder_get_project (placeholder); - glade_project_selection_set (project, GTK_WIDGET (placeholder), TRUE); + glade_project_selection_set (project, G_OBJECT (placeholder), TRUE); } } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) @@ -340,3 +339,21 @@ glade_placeholder_popup_menu (GtkWidget *widget) return TRUE; } + +GladeWidget * +glade_placeholder_get_parent (GladePlaceholder *placeholder) +{ + GtkWidget *widget; + GladeWidget *parent = NULL; + + g_return_val_if_fail (GLADE_IS_PLACEHOLDER (placeholder), NULL); + + for (widget = gtk_widget_get_parent (GTK_WIDGET (placeholder)); + widget != NULL; + widget = gtk_widget_get_parent (widget)) + { + if ((parent = glade_widget_get_from_gobject (widget)) != NULL) + break; + } + return parent; +} diff --git a/src/glade-placeholder.h b/src/glade-placeholder.h index 7e6beb27..58e1eb02 100644 --- a/src/glade-placeholder.h +++ b/src/glade-placeholder.h @@ -31,10 +31,9 @@ struct _GladePlaceholderClass }; -GType glade_placeholder_get_type (void) G_GNUC_CONST; - -GtkWidget *glade_placeholder_new (void); - +GType glade_placeholder_get_type (void) G_GNUC_CONST; +GtkWidget *glade_placeholder_new (void); +GladeWidget *glade_placeholder_get_parent (GladePlaceholder *placeholder); G_END_DECLS diff --git a/src/glade-popup.c b/src/glade-popup.c index 4b0ddffd..5fe66841 100644 --- a/src/glade-popup.c +++ b/src/glade-popup.c @@ -34,7 +34,8 @@ static void glade_popup_select_cb (GtkMenuItem *item, GladeWidget *widget) { if (widget) - glade_project_selection_set (widget->project, widget->widget, TRUE); + glade_project_selection_set + (widget->project, glade_widget_get_object (widget), TRUE); } static void @@ -72,10 +73,20 @@ glade_popup_placeholder_paste_cb (GtkMenuItem *item, glade_command_paste (placeholder); } +static void +glade_popup_add_item_cb (GtkMenuItem *item, + GladeWidget *widget) +{ + GladeSupportedChild *support = + g_object_get_data (G_OBJECT (item), "support"); + + /* XXX finish me !!! */ +} + /* * If stock_id != NULL, label is ignored */ -static void +static GtkWidget * glade_popup_append_item (GtkWidget *popup_menu, const gchar *stock_id, const gchar *label, @@ -96,6 +107,8 @@ glade_popup_append_item (GtkWidget *popup_menu, gtk_widget_set_sensitive (menu_item, sensitive); gtk_widget_show (menu_item); gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), menu_item); + + return menu_item; } static GtkWidget * @@ -126,6 +139,40 @@ glade_popup_populate_childs (GtkWidget* popup_menu, GladeWidget* parent) } } +static void +glade_popup_add_children (GtkWidget* popup_menu, GladeWidget *widget) +{ + GtkWidget *menu_item = + gtk_image_menu_item_new_from_stock (GTK_STOCK_ADD, NULL); + GtkWidget *add_menu = gtk_menu_new (); + GtkWidget *seperator = gtk_menu_item_new (); + GList *list; + + gtk_widget_show (menu_item); + gtk_widget_show (seperator); + gtk_widget_show (add_menu); + + gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), seperator); + gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), menu_item); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), add_menu); + + for (list = widget->widget_class->children; + list && list->data; list = list->next) + { + GladeSupportedChild *support = list->data; + GtkWidget *item; + + if (g_type_is_a (support->type, GTK_TYPE_WIDGET)) + continue; + + item = glade_popup_append_item (add_menu, NULL, g_type_name (support->type), + TRUE, glade_popup_add_item_cb, widget); + + g_object_set_data (G_OBJECT (item), "support", support); + } +} + + static GtkWidget * glade_popup_create_menu (GladeWidget *widget, gboolean add_childs) { @@ -144,6 +191,9 @@ glade_popup_create_menu (GladeWidget *widget, gboolean add_childs) glade_popup_append_item (popup_menu, GTK_STOCK_DELETE, NULL, TRUE, glade_popup_delete_cb, widget); + if (glade_widget_class_contains_non_widgets (widget->widget_class)) + glade_popup_add_children (popup_menu, widget); + if (add_childs && !g_type_is_a (widget->widget_class->type, GTK_TYPE_WINDOW)) { GladeWidget *parent = glade_widget_get_parent (widget); @@ -165,7 +215,7 @@ glade_popup_create_placeholder_menu (GladePlaceholder *placeholder) glade_popup_append_item (popup_menu, GTK_STOCK_PASTE, NULL, TRUE, glade_popup_placeholder_paste_cb, placeholder); - if ((parent = glade_util_get_parent(GTK_WIDGET (placeholder))) != NULL) + if ((parent = glade_placeholder_get_parent(placeholder)) != NULL) glade_popup_populate_childs(popup_menu, parent); return popup_menu; diff --git a/src/glade-project-view.c b/src/glade-project-view.c index 2d8469cf..dbb9bf34 100644 --- a/src/glade-project-view.c +++ b/src/glade-project-view.c @@ -187,7 +187,7 @@ glade_project_view_populate_model_real (GtkTreeStore *model, { GladeWidget *widget; - widget = glade_widget_get_from_gtk_widget (list->data); + widget = glade_widget_get_from_gobject (list->data); if (widget) { gtk_tree_store_append (model, &iter, parent_iter); @@ -224,13 +224,11 @@ glade_project_view_populate_model (GladeProjectView *view) return; /* Make a list of only the toplevel widgets */ - for (list = project->widgets; list; list = list->next) + for (list = project->objects; list; list = list->next) { - GtkWidget *widget; - - widget = GTK_WIDGET (list->data); - if (GTK_WIDGET_TOPLEVEL (widget)) - toplevels = g_list_append (toplevels, widget); + GObject *object = G_OBJECT (list->data); + if (GTK_WIDGET_TOPLEVEL (object)) + toplevels = g_list_append (toplevels, object); } /* add the widgets and recurse */ @@ -265,12 +263,17 @@ glade_project_view_add_item (GladeProjectView *view, parent); gtk_tree_store_append (model, &iter, parent_iter); - gtk_tree_store_set (model, &iter, - WIDGET_COLUMN, widget, - -1); + gtk_tree_store_set (model, &iter, WIDGET_COLUMN, widget, -1); + + + /* + XXX Add find any children and shuffle them around in the tree view. + */ + view->updating_selection = TRUE; - glade_project_selection_set (widget->project, widget->widget, TRUE); + glade_project_selection_set (widget->project, + glade_widget_get_object (widget), TRUE); view->updating_selection = FALSE; } @@ -389,7 +392,8 @@ glade_project_view_selection_changed_cb (GtkTreeSelection *selection, return TRUE; view->updating_selection = TRUE; - glade_project_selection_set (widget->project, widget->widget, TRUE); + glade_project_selection_set (widget->project, + glade_widget_get_object (widget), TRUE); view->updating_selection = FALSE; return TRUE; @@ -401,24 +405,28 @@ glade_project_view_item_activated_cb (GtkTreeView *view, GtkTreeViewColumn *column, gpointer notused) { - GladeWidget *widget; + GladeWidget *widget; + GObject *object; GtkTreeModel *model; - GtkTreeIter iter; - + GtkTreeIter iter; + model = gtk_tree_view_get_model (view); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (model, &iter, WIDGET_COLUMN, &widget, -1); - if (GTK_IS_WINDOW (widget->widget)) + if ((object = glade_widget_get_object (widget)) != NULL) { - if (GTK_WIDGET_VISIBLE (widget->widget)) - gtk_widget_hide (widget->widget); - else - gtk_window_present (GTK_WINDOW (widget->widget)); - } - else - { - gtk_widget_show (widget->widget); + if (GTK_IS_WINDOW (object)) + { + if (GTK_WIDGET_VISIBLE (object)) + gtk_widget_hide (GTK_WIDGET(object)); + else + gtk_window_present (GTK_WINDOW (object)); + } + else if (GTK_IS_WIDGET (object)) + { + gtk_widget_show (GTK_WIDGET(object)); + } } } diff --git a/src/glade-project-window.c b/src/glade-project-window.c index 31f76578..8085e747 100644 --- a/src/glade-project-window.c +++ b/src/glade-project-window.c @@ -328,13 +328,11 @@ do_close (GladeProjectWindow *gpw, GladeProject *project) gtk_item_factory_delete_item (gpw->item_factory, item_path); g_free (item_path); - for (list = project->widgets; list; list = list->next) + for (list = project->objects; list; list = list->next) { - GtkWidget *widget; - - widget = list->data; - if (GTK_WIDGET_TOPLEVEL (widget)) - gtk_widget_destroy (widget); + GObject *object = list->data; + if (GTK_WIDGET_TOPLEVEL (object)) + gtk_widget_destroy (GTK_WIDGET(object)); } gpw->projects = g_list_remove (gpw->projects, project); @@ -426,7 +424,7 @@ gpw_copy_cb (void) /* TODO: support multiple selected items */ if (list != NULL && list->next == NULL) { - GladeWidget *widget = glade_widget_get_from_gtk_widget (GTK_WIDGET (list->data)); + GladeWidget *widget = glade_widget_get_from_gobject (GTK_WIDGET (list->data)); if (widget) glade_command_copy (widget); @@ -444,7 +442,7 @@ gpw_cut_cb (void) /* TODO: support multiple selected items */ if (list != NULL && list->next == NULL) { - GladeWidget *widget = glade_widget_get_from_gtk_widget (GTK_WIDGET (list->data)); + GladeWidget *widget = glade_widget_get_from_gobject (GTK_WIDGET (list->data)); if (widget) glade_command_cut (widget); @@ -1320,7 +1318,7 @@ gpw_project_selection_changed_cb (GladeProject *project, num = g_list_length (list); if (num == 1 && !GLADE_IS_PLACEHOLDER (list->data)) glade_editor_load_widget (gpw->editor, - glade_widget_get_from_gtk_widget + glade_widget_get_from_gobject (GTK_WIDGET (list->data))); else glade_editor_load_widget (gpw->editor, NULL); diff --git a/src/glade-project.c b/src/glade-project.c index 6e0b80e1..69a0c8c8 100644 --- a/src/glade-project.c +++ b/src/glade-project.c @@ -101,7 +101,7 @@ glade_project_class_init (GladeProjectClass *class) g_signal_new ("add_widget", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GladeProjectClass, add_widget), + G_STRUCT_OFFSET (GladeProjectClass, add_object), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, @@ -112,7 +112,7 @@ glade_project_class_init (GladeProjectClass *class) g_signal_new ("remove_widget", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GladeProjectClass, remove_widget), + G_STRUCT_OFFSET (GladeProjectClass, remove_object), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, @@ -143,8 +143,8 @@ glade_project_class_init (GladeProjectClass *class) object_class->finalize = glade_project_finalize; object_class->dispose = glade_project_dispose; - class->add_widget = NULL; - class->remove_widget = NULL; + class->add_object = NULL; + class->remove_object = NULL; class->widget_name_changed = NULL; class->selection_changed = NULL; } @@ -153,7 +153,7 @@ static void glade_project_init (GladeProject *project) { project->name = NULL; - project->widgets = NULL; + project->objects = NULL; project->selection = NULL; project->undo_stack = NULL; project->prev_redo_item = NULL; @@ -212,8 +212,8 @@ glade_project_dispose (GObject *object) glade_project_list_unref (project->prev_redo_item); project->prev_redo_item = NULL; - glade_project_list_unref (project->widgets); - project->widgets = NULL; + glade_project_list_unref (project->objects); + project->objects = NULL; g_object_unref (project->tooltips); project->tooltips = NULL; @@ -267,46 +267,41 @@ glade_project_on_widget_notify (GladeWidget *widget, GParamSpec *arg, GladeProje case 'p': if (strcmp (arg->name, "project") == 0) - glade_project_remove_widget (project, glade_widget_get_widget (widget)); + glade_project_remove_object (project, glade_widget_get_object (widget)); } } /** - * glade_project_add_widget: - * @project: the project the widget is added to - * @widget: the GtkWidget to add + * glade_project_add_object: + * @project: the #GladeProject the widget is added to + * @object: the #GObject to add * - * Adds a widget to the project. + * Adds an object to the project. */ void -glade_project_add_widget (GladeProject *project, GtkWidget *widget) +glade_project_add_object (GladeProject *project, GObject *object) { - GladeWidget *gwidget; - + GladeWidget *gwidget; + GList *list, *children; + g_return_if_fail (GLADE_IS_PROJECT (project)); - g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (G_IS_OBJECT (object)); /* We don't list placeholders */ - if (GLADE_IS_PLACEHOLDER (widget)) + if (GLADE_IS_PLACEHOLDER (object)) return; - /* If it's a container add the children as well */ - if (GTK_IS_CONTAINER (widget)) - { - GList *list, *children; - GtkWidget *child; + if ((gwidget = glade_widget_get_from_gobject (object)) == NULL) + return; - children = gtk_container_get_children (GTK_CONTAINER (widget)); - for (list = children; list; list = list->next) - { - child = list->data; - glade_project_add_widget (project, child); - } + if ((children = glade_widget_class_container_get_children (gwidget->widget_class, + gwidget->object)) != NULL) + { + for (list = children; list && list->data; list = list->next) + glade_project_add_object (project, G_OBJECT (list->data)); g_list_free (children); } - gwidget = glade_widget_get_from_gtk_widget (widget); - /* The internal widgets (e.g. the label of a GtkButton) are handled * by gtk and don't have an associated GladeWidget: we don't want to * add these to our list. It would be nicer to have a flag to check @@ -319,12 +314,13 @@ glade_project_add_widget (GladeProject *project, GtkWidget *widget) return; glade_widget_set_project (gwidget, project); - g_hash_table_insert (project->widget_old_names, gwidget, g_strdup (glade_widget_get_name (gwidget))); + g_hash_table_insert (project->widget_old_names, + gwidget, g_strdup (glade_widget_get_name (gwidget))); - g_signal_connect (G_OBJECT (gwidget), "notify", (GCallback) glade_project_on_widget_notify, project); + g_signal_connect (G_OBJECT (gwidget), "notify", + (GCallback) glade_project_on_widget_notify, project); - project->widgets = g_list_prepend (project->widgets, widget); - g_object_ref (widget); + project->objects = g_list_prepend (project->objects, g_object_ref (object)); project->changed = TRUE; g_signal_emit (G_OBJECT (project), glade_project_signals [ADD_WIDGET], @@ -383,7 +379,7 @@ glade_project_release_widget_name (GladeProject *project, GladeWidget *glade_wid } /** - * glade_project_remove_widget: + * glade_project_remove_object: * @project: a #GladeProject * @widget: the #GtkWidget to remove * @@ -394,45 +390,36 @@ glade_project_release_widget_name (GladeProject *project, GladeWidget *glade_wid * way UNDO can work. */ void -glade_project_remove_widget (GladeProject *project, GtkWidget *widget) +glade_project_remove_object (GladeProject *project, GObject *object) { - GladeWidget *gwidget; - GList *widget_l; + GladeWidget *gwidget; + GList *link, *list, *children; g_return_if_fail (GLADE_IS_PROJECT (project)); - g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (G_IS_OBJECT (object)); - if (GLADE_IS_PLACEHOLDER (widget)) + if (GLADE_IS_PLACEHOLDER (object)) return; - /* If it's a container remove the children as well */ - if (GTK_IS_CONTAINER (widget)) + if ((gwidget = glade_widget_get_from_gobject (object)) == NULL) + return; + + if ((children = glade_widget_class_container_get_children (gwidget->widget_class, + gwidget->object)) != NULL) { - GList *list, *children; - GtkWidget *child; - - children = gtk_container_get_children (GTK_CONTAINER (widget)); - for (list = children; list; list = list->next) - { - child = list->data; - glade_project_remove_widget (project, child); - } + for (list = children; list && list->data; list = list->next) + glade_project_remove_object (project, G_OBJECT (list->data)); g_list_free (children); } - glade_project_selection_remove (project, widget, TRUE); + glade_project_selection_remove (project, object, TRUE); - gwidget = glade_widget_get_from_gtk_widget (widget); - if (!gwidget) - return; - - widget_l = g_list_find (project->widgets, widget); - if (widget_l != NULL) + if ((link = g_list_find (project->objects, object)) != NULL) { - g_object_unref (widget); + g_object_unref (object); glade_project_release_widget_name (project, gwidget, glade_widget_get_name (gwidget)); - project->widgets = g_list_delete_link (project->widgets, widget_l); + project->objects = g_list_delete_link (project->objects, link); } project->changed = TRUE; @@ -483,10 +470,10 @@ glade_project_get_widget_by_name (GladeProject *project, const gchar *name) g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL); g_return_val_if_fail (name != NULL, NULL); - for (list = project->widgets; list; list = list->next) { + for (list = project->objects; list; list = list->next) { GladeWidget *widget; - widget = glade_widget_get_from_gtk_widget (list->data); + widget = glade_widget_get_from_gobject (list->data); g_return_val_if_fail (widget->name != NULL, NULL); if (strcmp (widget->name, name) == 0) return widget; @@ -551,7 +538,7 @@ glade_project_new_widget_name (GladeProject *project, const char *base_name) void glade_project_selection_clear (GladeProject *project, gboolean emit_signal) { - GtkWidget *widget; + GObject *object; GList *list; g_return_if_fail (GLADE_IS_PROJECT (project)); @@ -561,8 +548,8 @@ glade_project_selection_clear (GladeProject *project, gboolean emit_signal) for (list = project->selection; list; list = list->next) { - widget = list->data; - glade_util_remove_nodes (widget); + object = list->data; + glade_util_remove_selection (object); } g_list_free (project->selection); @@ -584,20 +571,20 @@ glade_project_selection_clear (GladeProject *project, gboolean emit_signal) */ void glade_project_selection_remove (GladeProject *project, - GtkWidget *widget, - gboolean emit_signal) + GObject *object, + gboolean emit_signal) { g_return_if_fail (GLADE_IS_PROJECT (project)); - g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (G_IS_OBJECT (object)); - if (!glade_util_has_nodes (widget)) + if (!glade_util_has_selection (object)) return; - glade_util_remove_nodes (widget); + glade_util_remove_selection (object); if (project) { - project->selection = g_list_remove (project->selection, widget); + project->selection = g_list_remove (project->selection, object); if (emit_signal) glade_project_selection_changed (project); } @@ -615,24 +602,23 @@ glade_project_selection_remove (GladeProject *project, */ void glade_project_selection_add (GladeProject *project, - GtkWidget *widget, - gboolean emit_signal) + GObject *object, + gboolean emit_signal) { GladeProjectWindow *gpw; - gboolean has_nodes; g_return_if_fail (GLADE_IS_PROJECT (project)); - g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (G_IS_OBJECT (object)); gpw = glade_project_window_get (); - if (glade_util_has_nodes (widget)) + if (glade_util_has_selection (object)) return; - glade_util_add_nodes (widget); + glade_util_add_selection (object); if (project) { - project->selection = g_list_prepend (project->selection, widget); + project->selection = g_list_prepend (project->selection, object); if (emit_signal) glade_project_selection_changed (project); } @@ -650,20 +636,20 @@ glade_project_selection_add (GladeProject *project, */ void glade_project_selection_set (GladeProject *project, - GtkWidget *widget, - gboolean emit_signal) + GObject *object, + gboolean emit_signal) { GladeProjectWindow *gpw; g_return_if_fail (GLADE_IS_PROJECT (project)); - g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (G_IS_OBJECT (object)); gpw = glade_project_window_get (); - if (glade_util_has_nodes (widget)) + if (glade_util_has_selection (object)) return; glade_project_selection_clear (project, FALSE); - glade_project_selection_add (project, widget, emit_signal); + glade_project_selection_add (project, object, emit_signal); } /** @@ -702,12 +688,12 @@ glade_project_write (const GladeProject *project) (GDestroyNotify)g_free, NULL); - for (i = 0, list = project->widgets; list; list = list->next) + for (i = 0, list = project->objects; list; list = list->next) { GladeWidget *widget; GladeWidgetInfo *info; - widget = glade_widget_get_from_gtk_widget (list->data); + widget = glade_widget_get_from_gobject (list->data); /* * Append toplevel widgets. Each widget then takes @@ -724,9 +710,9 @@ glade_project_write (const GladeProject *project) } } interface->n_toplevels = i; - interface->toplevels = (GladeWidgetInfo **) g_new (GladeWidgetInfo *, i); - for (i = 0, list = tops; list; list = list->next, ++i) - interface->toplevels[i] = list->data; + interface->toplevels = (GladeWidgetInfo **) g_new (GladeWidgetInfo *, i); + for (i = 0, list = tops; list; list = list->next, ++i) + interface->toplevels[i] = list->data; g_list_free (tops); @@ -743,7 +729,7 @@ glade_project_new_from_interface (GladeInterface *interface) project = glade_project_new (FALSE); project->changed = FALSE; project->selection = NULL; - project->widgets = NULL; + project->objects = NULL; if (interface->n_requires) g_warning ("We currently do not support projects requiring additional libs"); @@ -756,8 +742,9 @@ glade_project_new_from_interface (GladeInterface *interface) g_warning ("Failed to read a <widget> tag"); continue; } - project->widgets = g_list_prepend (project->widgets, widget->widget); - g_object_ref (widget->widget); + project->objects = g_list_prepend (project->objects, + glade_widget_get_object(widget)); + g_object_ref (glade_widget_get_object(widget)); } return project; @@ -787,7 +774,7 @@ glade_project_open (const gchar *path) glade_interface_destroy (interface); if (project) - { + { project->path = g_strdup_printf ("%s", path); g_free (project->name); project->name = g_path_get_basename (project->path); @@ -821,7 +808,7 @@ glade_project_save (GladeProject *project, const gchar *path) glade_interface_destroy (interface); if (path != project->path) - { + { g_free (project->path); project->path = g_strdup_printf ("%s", path); } diff --git a/src/glade-project.h b/src/glade-project.h index fff186ae..6adac7a9 100644 --- a/src/glade-project.h +++ b/src/glade-project.h @@ -33,8 +33,8 @@ struct _GladeProject * requested */ - GList *widgets; /* A list of #GtkWidgets that make up this project. - * The widgets are stored in no particular order. + GList *objects; /* A list of #GObjects that make up this project. + * The objects are stored in no particular order. */ GList *selection; /* We need to keep the selection in the project @@ -55,41 +55,42 @@ struct _GladeProjectClass { GObjectClass parent_class; - void (*add_widget) (GladeProject *project, + void (*add_object) (GladeProject *project, GladeWidget *widget); - void (*remove_widget) (GladeProject *project, + void (*remove_object) (GladeProject *project, GladeWidget *widget); void (*widget_name_changed) (GladeProject *project, GladeWidget *widget); void (*selection_changed) (GladeProject *project); }; +GType glade_project_get_type (void); -GType glade_project_get_type (void); - -GladeProject *glade_project_new (gboolean untitled); - -GladeProject *glade_project_open (const gchar *path); -gboolean glade_project_save (GladeProject *project, const gchar *path); - -void glade_project_add_widget (GladeProject *project, GtkWidget *widget); -void glade_project_remove_widget (GladeProject *project, GtkWidget *widget); - -GladeWidget *glade_project_get_widget_by_name (GladeProject *project, const char *name); -char *glade_project_new_widget_name (GladeProject *project, const char *base_name); - -void glade_project_widget_name_changed (GladeProject *project, GladeWidget *widget, const char *old_name); -GtkTooltips *glade_project_get_tooltips (GladeProject *project); +GladeProject *glade_project_new (gboolean untitled); +GladeProject *glade_project_open (const gchar *path); +gboolean glade_project_save (GladeProject *project, const gchar *path); +void glade_project_add_object (GladeProject *project, GObject *object); +void glade_project_remove_object (GladeProject *project, GObject *object); +GladeWidget *glade_project_get_widget_by_name (GladeProject *project, const char *name); +char *glade_project_new_widget_name (GladeProject *project, const char *base_name); +void glade_project_widget_name_changed (GladeProject *project, GladeWidget *widget, + const char *old_name); +GtkTooltips *glade_project_get_tooltips (GladeProject *project); /* Selection */ -void glade_project_selection_set (GladeProject *project, GtkWidget *widget, gboolean emit_signal); -void glade_project_selection_add (GladeProject *project, GtkWidget *widget, gboolean emit_signal); -void glade_project_selection_remove (GladeProject *project, GtkWidget *widget, gboolean emit_signal); -void glade_project_selection_clear (GladeProject *project, gboolean emit_signal); -void glade_project_selection_changed (GladeProject *project); - -GList *glade_project_selection_get (GladeProject *project); - +void glade_project_selection_set (GladeProject *project, + GObject *object, + gboolean emit_signal); +void glade_project_selection_add (GladeProject *project, + GObject *object, + gboolean emit_signal); +void glade_project_selection_remove (GladeProject *project, + GObject *object, + gboolean emit_signal); +void glade_project_selection_clear (GladeProject *project, + gboolean emit_signal); +void glade_project_selection_changed (GladeProject *project); +GList *glade_project_selection_get (GladeProject *project); G_END_DECLS diff --git a/src/glade-property-class.c b/src/glade-property-class.c index c220c3a3..a16e9bbe 100644 --- a/src/glade-property-class.c +++ b/src/glade-property-class.c @@ -34,6 +34,7 @@ #include "glade-parameter.h" #include "glade-property.h" #include "glade-property-class.h" +#include "glade-editor.h" #include "glade-debug.h" /** @@ -479,13 +480,12 @@ glade_property_class_new_from_spec (GParamSpec *spec) property_class->pspec = spec; - /* We dont edit objects or pointers as properties. + /* Register only editable properties. */ - if (G_IS_PARAM_SPEC_OBJECT(property_class->pspec) || - G_IS_PARAM_SPEC_POINTER(property_class->pspec)) + if (!glade_editor_editable_property (property_class->pspec)) goto lblError; - property_class->id = g_strdup (spec->name); + property_class->id = g_strdup (spec->name); property_class->name = g_strdup (g_param_spec_get_nick (spec)); if (!property_class->id || !property_class->name) { diff --git a/src/glade-property.c b/src/glade-property.c index cc25929c..9c722788 100644 --- a/src/glade-property.c +++ b/src/glade-property.c @@ -43,35 +43,66 @@ * Returns: */ GladeProperty * -glade_property_new (GladePropertyClass *class, GladeWidget *widget) +glade_property_new (GladePropertyClass *class, GladeWidget *widget, GValue *value) { GladeProperty *property; g_return_val_if_fail (GLADE_IS_PROPERTY_CLASS (class), NULL); - g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL); - property = g_new0 (GladeProperty, 1); - property->class = class; - property->widget = widget; - property->value = g_new0 (GValue, 1); + property = g_new0 (GladeProperty, 1); + property->class = class; + property->widget = widget; + property->value = value; property->enabled = TRUE; - /* Create an empty default if the class does not specify a default - * value */ - if (!class->def) - { - property->value = glade_property_class_make_gvalue_from_string (class, ""); - return property; - } - if (G_IS_PARAM_SPEC_DOUBLE (class->pspec) || G_IS_PARAM_SPEC_FLOAT (class->pspec) || + G_IS_PARAM_SPEC_LONG (class->pspec) || + G_IS_PARAM_SPEC_ULONG (class->pspec) || + G_IS_PARAM_SPEC_INT64 (class->pspec) || + G_IS_PARAM_SPEC_UINT64 (class->pspec) || G_IS_PARAM_SPEC_INT (class->pspec) || G_IS_PARAM_SPEC_UINT (class->pspec)) property->enabled = class->optional_default; - g_value_init (property->value, class->def->g_type); - g_value_copy (class->def, property->value); + /* Create an empty default if the class does not specify a default value */ + if (property->value == NULL) + { + if (!class->def) + property->value = + glade_property_class_make_gvalue_from_string (class, ""); + else + { + property->value = g_new0 (GValue, 1); + g_value_init (property->value, class->def->g_type); + g_value_copy (class->def, property->value); + } + } + return property; +} + +/** + * glade_property_dup: + * @template: + * @widget: + * + * TODO: write me + * + * Returns: + */ +GladeProperty * +glade_property_dup (GladeProperty *template, GladeWidget *widget) +{ + GladeProperty *property; + + property = g_new0 (GladeProperty, 1); + property->class = template->class; + property->widget = widget; + property->value = g_new0 (GValue, 1); + property->enabled = template->enabled; + + g_value_init (property->value, template->value->g_type); + g_value_copy (template->value, property->value); return property; } @@ -106,14 +137,15 @@ glade_property_set_property (GladeProperty *property, const GValue *value) { if (property->class->packing) { - GladeWidget *parent = glade_widget_get_parent (property->widget); - GtkContainer *container = GTK_CONTAINER (glade_widget_get_widget (parent)); - GtkWidget *child = glade_widget_get_widget (property->widget); - gtk_container_child_set_property (container, child, property->class->id, value); + GladeWidget *parent = glade_widget_get_parent (property->widget); + GladeWidget *child = property->widget; + glade_widget_class_container_set_property (parent->widget_class, + parent->object, child->object, + property->class->id, value); } else { - GObject *gobject = G_OBJECT (glade_widget_get_widget (property->widget)); + GObject *gobject = G_OBJECT (glade_widget_get_object (property->widget)); g_object_set_property (gobject, property->class->id, value); } } @@ -140,8 +172,7 @@ glade_property_set (GladeProperty *property, const GValue *value) if (property->class->verify_function) { - GObject *object = - G_OBJECT(glade_widget_get_widget (property->widget)); + GObject *object = glade_widget_get_object (property->widget); if (property->class->verify_function (object, value) == FALSE) return; } @@ -176,8 +207,8 @@ glade_property_sync (GladeProperty *property) if (property->class->set_function) /* if there is a custom set_property, use it */ - (*property->class->set_function) (G_OBJECT (property->widget->widget), - property->value); + (*property->class->set_function) + (glade_widget_get_object (property->widget), property->value); else if (property->class->construct_only) { /* In the case of construct_only, the widget must be rebuilt, here we @@ -190,27 +221,28 @@ glade_property_sync (GladeProperty *property) { if ((selection = glade_project_selection_get (property->widget->project)) != NULL && - g_list_find(selection, property->widget->widget) != NULL) + g_list_find(selection, + glade_widget_get_object (property->widget)) != NULL) { reselect = TRUE; - glade_project_selection_remove(property->widget->project, - property->widget->widget, - FALSE); + glade_project_selection_remove + (property->widget->project, + glade_widget_get_object (property->widget), FALSE); } - glade_project_remove_widget (property->widget->project, - property->widget->widget); + glade_project_remove_object (property->widget->project, + glade_widget_get_object (property->widget)); } glade_widget_rebuild (property->widget); if (property->widget->project) { - glade_project_add_widget (property->widget->project, - property->widget->widget); + glade_project_add_object (property->widget->project, + glade_widget_get_object (property->widget)); if (reselect) - glade_project_selection_add(property->widget->project, - property->widget->widget, - TRUE); + glade_project_selection_add + (property->widget->project, + glade_widget_get_object (property->widget), TRUE); } } else diff --git a/src/glade-property.h b/src/glade-property.h index 4c5d3c42..b0850a92 100644 --- a/src/glade-property.h +++ b/src/glade-property.h @@ -40,7 +40,9 @@ struct _GladeProperty }; -GladeProperty *glade_property_new (GladePropertyClass *class, GladeWidget *widget); +GladeProperty *glade_property_new (GladePropertyClass *class, + GladeWidget *widget, + GValue *value); void glade_property_free (GladeProperty *property); @@ -51,6 +53,7 @@ void glade_property_sync (GladeProperty *property); gboolean glade_property_write (GArray *props, GladeProperty *property, GladeInterface *interface); +GladeProperty *glade_property_dup (GladeProperty *template, GladeWidget *widget); G_END_DECLS diff --git a/src/glade-utils.c b/src/glade-utils.c index d2b4d13e..f332044d 100644 --- a/src/glade-utils.c +++ b/src/glade-utils.c @@ -67,8 +67,8 @@ glade_util_widget_set_tooltip (GtkWidget *widget, const gchar *str) * * Returns: */ -gchar * -glade_util_compose_get_type_func (gchar *name) +static gchar * +glade_util_compose_get_type_func (const gchar *name) { gchar *retval; GString *tmp; @@ -114,27 +114,32 @@ glade_util_get_type_from_name (const gchar *name) { static GModule *allsymbols = NULL; GType (*get_type) (); - GType type; + GType type = 0; + gchar *func_name; - if (!allsymbols) - allsymbols = g_module_open (NULL, 0); + if ((func_name = glade_util_compose_get_type_func (name)) != NULL) + { + + if (!allsymbols) + allsymbols = g_module_open (NULL, 0); - if (!g_module_symbol (allsymbols, name, - (gpointer) &get_type)) { - g_warning (_("We could not find the symbol \"%s\""), - name); - return FALSE; + if (g_module_symbol (allsymbols, func_name, + (gpointer) &get_type)) + { + g_assert (get_type); + type = get_type (); + } else { + g_warning (_("We could not find the symbol \"%s\""), + func_name); + } + g_free (func_name); } - g_assert (get_type); - type = get_type (); - if (type == 0) { g_warning(_("Could not get the type from \"%s"), name); - return 0; } - + return type; } @@ -685,15 +690,11 @@ glade_util_draw_nodes_idle (GdkWindow *expose_win) GdkGC *gc; GList *elem; - /* Find the corresponding GtkWidget and GladeWidget. */ gdk_window_get_user_data (expose_win, (gpointer *)&expose_widget); - if ((expose_gwidget = glade_widget_get_from_gtk_widget(expose_widget)) == NULL) - { - expose_gwidget = glade_util_get_parent (expose_widget); - } - g_assert(expose_gwidget); - + if ((expose_gwidget = glade_widget_get_from_gobject(expose_widget)) == NULL) + goto out; + /* Check that the window is still alive. */ if (!gdk_window_is_viewable (expose_win)) goto out; @@ -745,7 +746,7 @@ glade_util_draw_nodes_idle (GdkWindow *expose_win) out: /* Remove the reference added in glade_util_queue_draw_nodes(). */ - g_object_unref(G_OBJECT(expose_gwidget)); + g_object_unref (G_OBJECT (expose_win)); /* Return FALSE so the idle handler isn't called again. */ return FALSE; @@ -764,28 +765,13 @@ glade_util_draw_nodes_idle (GdkWindow *expose_win) void glade_util_queue_draw_nodes (GdkWindow *window) { - GtkWidget *widget; - GladeWidget *gwidget; - g_return_if_fail (GDK_IS_WINDOW (window)); - gdk_window_get_user_data (window, (gpointer *)&widget); - if ((gwidget = glade_widget_get_from_gtk_widget(widget)) == NULL) - { - gwidget = glade_util_get_parent (widget); - } - - if (gwidget) { - g_idle_add_full (GLADE_DRAW_NODES_IDLE_PRIORITY, - (GSourceFunc)glade_util_draw_nodes_idle, - window, NULL); + g_idle_add_full (GLADE_DRAW_NODES_IDLE_PRIORITY, + (GSourceFunc)glade_util_draw_nodes_idle, + window, NULL); - /* We need to ref the glade widget, to make sure it isn't freed before - * our idle function is called. We unref it there. (ofcourse, the glade - * widget holds reference to everything we need there). - */ - g_object_ref (G_OBJECT(gwidget)); - } + g_object_ref (G_OBJECT (window)); } @@ -796,11 +782,12 @@ glade_util_queue_draw_nodes (GdkWindow *window) * TODO: write me */ void -glade_util_add_nodes (GtkWidget *widget) +glade_util_add_selection (GObject *object) { - g_object_set_data (G_OBJECT (widget), GLADE_UTIL_HAS_NODES, + g_object_set_data (object, GLADE_UTIL_HAS_NODES, GINT_TO_POINTER (1)); - gtk_widget_queue_draw (widget); + if (GTK_IS_WIDGET (object)) + gtk_widget_queue_draw (GTK_WIDGET (object)); } /** @@ -810,13 +797,16 @@ glade_util_add_nodes (GtkWidget *widget) * TODO: write me */ void -glade_util_remove_nodes (GtkWidget *widget) +glade_util_remove_selection (GObject *object) { - g_object_set_data (G_OBJECT (widget), GLADE_UTIL_HAS_NODES, GINT_TO_POINTER (0)); + g_object_set_data (object, GLADE_UTIL_HAS_NODES, GINT_TO_POINTER (0)); /* We redraw the parent, since the selection rectangle may not be cleared if we just redraw the widget itself. */ - gtk_widget_queue_draw (widget->parent ? widget->parent : widget); + if (GTK_IS_WIDGET (object)) + gtk_widget_queue_draw (GTK_WIDGET (object)->parent ? + GTK_WIDGET (object)->parent : + GTK_WIDGET (object)); } /** @@ -826,10 +816,10 @@ glade_util_remove_nodes (GtkWidget *widget) * Returns: %TRUE if @widget has nodes, %FALSE otherwise */ gboolean -glade_util_has_nodes (GtkWidget *widget) +glade_util_has_selection (GObject *object) { return GPOINTER_TO_INT (g_object_get_data - (G_OBJECT (widget), GLADE_UTIL_HAS_NODES)) != 0; + (object, GLADE_UTIL_HAS_NODES)) != 0; } /** @@ -860,7 +850,7 @@ glade_util_delete_selection (GladeProject *project) for (list = free_me; list; list = list->next) { GladeWidget *glade_widget; - glade_widget = glade_widget_get_from_gtk_widget (list->data); + glade_widget = glade_widget_get_from_gobject (list->data); if (glade_widget) glade_command_delete (glade_widget); } @@ -868,35 +858,6 @@ glade_util_delete_selection (GladeProject *project) g_list_free (free_me); } -/** - * glade_util_get_parent: - * @w: a #GtkWidget - * - * TODO: write me - * - * Returns: - */ -GladeWidget * -glade_util_get_parent (GtkWidget *w) -{ - GtkWidget *widget = w; - GladeWidget *parent = NULL; - - do - { - widget = gtk_widget_get_parent (widget); - if (widget != NULL) - { - parent = glade_widget_get_from_gtk_widget (widget); - if (parent != NULL) - return parent; - } - } - while (widget != NULL); - - return NULL; -} - /* * taken from gtk... maybe someday we can convince them to * expose gtk_container_get_all_children diff --git a/src/glade-utils.h b/src/glade-utils.h index 06d4a28a..7806d5c5 100644 --- a/src/glade-utils.h +++ b/src/glade-utils.h @@ -17,7 +17,6 @@ enum _GladeUtilFileDialogType void glade_util_widget_set_tooltip (GtkWidget *widget, const gchar *str); -gchar *glade_util_compose_get_type_func (gchar *name); GType glade_util_get_type_from_name (const gchar *name); GParamSpec *glade_utils_get_pspec_from_funcname (const gchar *funcname); void glade_util_ui_warn (GtkWidget *parent, const gchar *warning); @@ -42,9 +41,9 @@ char *glade_util_duplicate_underscores (const char *name); void glade_util_delete_selection (GladeProject *project); -void glade_util_add_nodes (GtkWidget *widget); -void glade_util_remove_nodes (GtkWidget *widget); -gboolean glade_util_has_nodes (GtkWidget *widget); +void glade_util_add_selection (GObject *object); +void glade_util_remove_selection (GObject *object); +gboolean glade_util_has_selection (GObject *object); void glade_util_queue_draw_nodes (GdkWindow *window); GladeWidget *glade_util_get_parent (GtkWidget *w); diff --git a/src/glade-widget-class.c b/src/glade-widget-class.c index eac5a87f..20cdb474 100644 --- a/src/glade-widget-class.c +++ b/src/glade-widget-class.c @@ -40,6 +40,7 @@ #include "glade-property.h" #include "glade-property-class.h" #include "glade-catalog.h" +#include "glade-signal.h" #include "glade-parameter.h" #include "glade-debug.h" @@ -47,6 +48,14 @@ static GHashTable *widget_classes = NULL; +static void +glade_widget_class_free_child (GladeSupportedChild *child) +{ + g_list_foreach (child->properties, (GFunc) glade_property_class_free, NULL); + g_list_free (child->properties); + g_free (child); +} + /** * glade_widget_class_free: * @widget_class: a #GladeWidgetClass @@ -62,13 +71,13 @@ glade_widget_class_free (GladeWidgetClass *widget_class) g_free (widget_class->generic_name); g_free (widget_class->name); - g_list_foreach (widget_class->properties, (GFunc) g_free, NULL); + g_list_foreach (widget_class->properties, (GFunc) glade_property_class_free, NULL); g_list_free (widget_class->properties); - g_list_foreach (widget_class->child_properties, (GFunc) g_free, NULL); - g_list_free (widget_class->child_properties); + g_list_foreach (widget_class->children, (GFunc) glade_widget_class_free_child, NULL); + g_list_free (widget_class->children); - g_list_foreach (widget_class->signals, (GFunc) g_free, NULL); + g_list_foreach (widget_class->signals, (GFunc) glade_signal_free, NULL); g_list_free (widget_class->signals); } @@ -193,6 +202,35 @@ glade_widget_class_list_child_properties (GladeWidgetClass *class) return list; } +static GList * +glade_widget_class_list_children (GladeWidgetClass *class) +{ + GladeSupportedChild *child; + GList *children = NULL; + + /* Implicitly handle GtkContainer and derivitive types and retrieve packing properties. + */ + if (g_type_is_a (class->type, GTK_TYPE_CONTAINER)) + { + child = g_new0 (GladeSupportedChild, 1); + child->type = GTK_TYPE_WIDGET; + child->properties = glade_widget_class_list_child_properties (class); + + child->add = (GladeAddChildFunc) gtk_container_add; + child->remove = (GladeRemoveChildFunc) gtk_container_remove; + child->get_children = (GladeGetChildrenFunc) gtk_container_get_children; + child->get_all_children = + (GladeGetChildrenFunc) glade_util_container_get_all_children; + child->set_property = + (GladeChildSetPropertyFunc) gtk_container_child_set_property; + child->get_property = + (GladeChildGetPropertyFunc) gtk_container_child_get_property; + + children = g_list_append (children, child); + } + return children; +} + static GList * glade_widget_class_list_signals (GladeWidgetClass *class) { @@ -253,8 +291,8 @@ glade_widget_class_update_properties_from_node (GladeXmlNode *node, GladeXmlNode *child; GList *properties = *pproperties; - child = glade_xml_node_get_children (node); - for (; child; child = glade_xml_node_next (child)) + for (child = glade_xml_node_get_children (node); + child; child = glade_xml_node_next (child)) { gchar *id; GList *list; @@ -306,6 +344,117 @@ glade_widget_class_update_properties_from_node (GladeXmlNode *node, } } +static gint +glade_widget_class_find_child_by_type (GladeSupportedChild *child, GType type) +{ + return child->type - type; +} + +static void +glade_widget_class_load_function (GladeXmlNode *node, + GModule *module, + gchar *tagname, + void **func_location) +{ + gchar *buff; + if ((buff = glade_xml_get_value_string (node, tagname)) != NULL) + { + if (!g_module_symbol (module, buff, func_location)) + g_warning ("Could not find %s in %s\n", + buff, g_module_name (module)); + g_free (buff); + } +} + +static void +glade_widget_class_update_children_from_node (GladeXmlNode *node, + GladeWidgetClass *widget_class) +{ + GladeSupportedChild *child; + GladeXmlNode *child_node, *properties; + gchar *buff; + GList *list; + GType type; + + for (child_node = glade_xml_node_get_children (node); + child_node; + child_node = glade_xml_node_next (child_node)) + { + + if (!glade_xml_node_verify (child_node, GLADE_TAG_CHILD)) + continue; + + /* Use alot of emacs realastate to ensure that we have a type. */ + if ((buff = glade_xml_get_value_string (child_node, GLADE_TAG_TYPE)) != NULL) + { + if ((type = glade_util_get_type_from_name (buff)) == 0) + { + g_free (buff); + continue; + } + g_free (buff); + } else { + g_warning ("Child specified without a type, ignoring"); + continue; + } + + if (widget_class->children && + (list = g_list_find_custom + (widget_class->children, GINT_TO_POINTER(type), + (GCompareFunc)glade_widget_class_find_child_by_type)) != NULL) + { + child = (GladeSupportedChild *)list->data; + } + else + { + child = g_new (GladeSupportedChild, 1); + child->type = type; + widget_class->children = g_list_append (widget_class->children, child); + } + + if (widget_class->module) + { + glade_widget_class_load_function (child_node, widget_class->module, + GLADE_TAG_ADD_CHILD_FUNCTION, + (void **)&child->add); + glade_widget_class_load_function (child_node, widget_class->module, + GLADE_TAG_REMOVE_CHILD_FUNCTION, + (void **)&child->remove); + glade_widget_class_load_function (child_node, widget_class->module, + GLADE_TAG_GET_CHILDREN_FUNCTION, + (void **)&child->get_children); + glade_widget_class_load_function (child_node, widget_class->module, + GLADE_TAG_GET_ALL_CHILDREN_FUNCTION, + (void **)&child->get_all_children); + glade_widget_class_load_function (child_node, widget_class->module, + GLADE_TAG_CHILD_SET_PROP_FUNCTION, + (void **)&child->set_property); + glade_widget_class_load_function (child_node, widget_class->module, + GLADE_TAG_CHILD_GET_PROP_FUNCTION, + (void **)&child->get_property); + glade_widget_class_load_function (child_node, widget_class->module, + GLADE_TAG_FILL_EMPTY_FUNCTION, + (void **)&child->fill_empty); + glade_widget_class_load_function (child_node, widget_class->module, + GLADE_TAG_REPLACE_CHILD_FUNCTION, + (void **)&child->replace_child); + } + + /* if we found a <Properties> tag on the xml file, we add the + * properties that we read from the xml file to the class. + */ + if ((properties = + glade_xml_search_child (child_node, GLADE_TAG_PROPERTIES)) != NULL) + { + glade_widget_class_update_properties_from_node + (properties, widget_class, &child->properties); + + for (list = child->properties; list != NULL; list = list->next) + ((GladePropertyClass *)list->data)->packing = TRUE; + } + } +} + /** * glade_widget_class_extend_with_file: * @filename: complete path name of the xml file with the description of the @@ -325,13 +474,6 @@ glade_widget_class_extend_with_file (GladeWidgetClass *widget_class, const char GladeXmlDoc *doc; GladeXmlNode *properties; GladeXmlNode *node; - char *replace_child_function_name; - char *post_create_function_name; - char *pre_create_function_name; - char *fill_empty_function_name; - char *get_internal_child_function_name; - char *child_property_applies_function_name; - GList *tmp; g_return_val_if_fail (filename != NULL, FALSE); @@ -347,72 +489,21 @@ glade_widget_class_extend_with_file (GladeWidgetClass *widget_class, const char return FALSE; } - replace_child_function_name = - glade_xml_get_value_string (node, GLADE_TAG_REPLACE_CHILD_FUNCTION); - - if (replace_child_function_name && widget_class->module) + if (widget_class->module) { - if (!g_module_symbol (widget_class->module, - replace_child_function_name, - (void **) &widget_class->replace_child)) - g_warning ("Could not find %s\n", replace_child_function_name); + glade_widget_class_load_function (node, widget_class->module, + GLADE_TAG_POST_CREATE_FUNCTION, + (void **)&widget_class->post_create_function); + + glade_widget_class_load_function (node, widget_class->module, + GLADE_TAG_GET_INTERNAL_CHILD_FUNCTION, + (void **)&widget_class->get_internal_child); + + glade_widget_class_load_function (node, widget_class->module, + GLADE_TAG_CHILD_PROPERTY_APPLIES_FUNCTION, + (void **) + &widget_class->child_property_applies); } - g_free (replace_child_function_name); - - pre_create_function_name = - glade_xml_get_value_string (node, GLADE_TAG_PRE_CREATE_FUNCTION); - if (pre_create_function_name && widget_class->module) - { - if (!g_module_symbol (widget_class->module, - pre_create_function_name, - (void **) &widget_class->pre_create_function)) - g_warning ("Could not find %s\n", pre_create_function_name); - } - g_free (pre_create_function_name); - - post_create_function_name = - glade_xml_get_value_string (node, GLADE_TAG_POST_CREATE_FUNCTION); - if (post_create_function_name && widget_class->module) - { - if (!g_module_symbol (widget_class->module, - post_create_function_name, - (void **) &widget_class->post_create_function)) - g_warning ("Could not find %s\n", post_create_function_name); - } - g_free (post_create_function_name); - - fill_empty_function_name = - glade_xml_get_value_string (node, GLADE_TAG_FILL_EMPTY_FUNCTION); - if (fill_empty_function_name && widget_class->module) - { - if (!g_module_symbol (widget_class->module, - fill_empty_function_name, - (void **) &widget_class->fill_empty)) - 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); - - child_property_applies_function_name = - glade_xml_get_value_string (node, GLADE_TAG_CHILD_PROPERTY_APPLIES_FUNCTION); - if (child_property_applies_function_name && widget_class->module) - { - if (!g_module_symbol (widget_class->module, - child_property_applies_function_name, - (void **) &widget_class->child_property_applies)) - g_warning ("Could not find %s\n", child_property_applies_function_name); - } - g_free (child_property_applies_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. @@ -422,19 +513,9 @@ glade_widget_class_extend_with_file (GladeWidgetClass *widget_class, const char glade_widget_class_update_properties_from_node (properties, widget_class, &widget_class->properties); - /* if we found a <ChildProperties> tag on the xml file, we add the - * properties that we read from the xml file to the class. - */ - properties = glade_xml_search_child (node, GLADE_TAG_CHILD_PROPERTIES); + properties = glade_xml_search_child (node, GLADE_TAG_CHILDREN); if (properties) - glade_widget_class_update_properties_from_node - (properties, widget_class, &widget_class->child_properties); - - for (tmp = widget_class->child_properties; tmp != NULL; tmp = tmp->next) - { - GladePropertyClass *property_class = tmp->data; - property_class->packing = TRUE; - } + glade_widget_class_update_children_from_node (properties, widget_class); glade_xml_context_destroy (context); return TRUE; @@ -486,7 +567,8 @@ glade_widget_class_merge_properties (GList **widget_properties, GList *parent_pr } /* if not found, prepend a clone of the parent's one; if found - * but the parent one was modified substitute it. + * but the parent one was modified (and not the child one) + * substitute it. */ if (!list2) { @@ -495,7 +577,7 @@ glade_widget_class_merge_properties (GList **widget_properties, GList *parent_pr property_class = glade_property_class_clone (parent_p_class); *widget_properties = g_list_prepend (*widget_properties, property_class); } - else if (parent_p_class->is_modified) + else if (parent_p_class->is_modified && !child_p_class->is_modified) { glade_property_class_free (child_p_class); list2->data = glade_property_class_clone (parent_p_class); @@ -503,6 +585,97 @@ glade_widget_class_merge_properties (GList **widget_properties, GList *parent_pr } } +static GladeSupportedChild * +glade_widget_class_clone_child (GladeSupportedChild *child) +{ + GladeSupportedChild *clone; + GList *props; + + clone = g_new0 (GladeSupportedChild, 1); + + clone->type = child->type; + clone->add = child->add; + clone->get_children = child->get_children; + clone->set_property = child->set_property; + clone->get_property = child->get_property; + clone->fill_empty = child->fill_empty; + clone->replace_child = child->replace_child; + + for (props = child->properties; + props && props->data; + props = props->next) + { + clone->properties = + g_list_prepend (clone->properties, + glade_property_class_clone (props->data)); + } + clone->properties = g_list_reverse (clone->properties); + + return clone; +} + +static void +glade_widget_class_merge_child (GladeSupportedChild *widgets_child, + GladeSupportedChild *parents_child) +{ + if (!widgets_child->add) + widgets_child->add = parents_child->add; + if (!widgets_child->remove) + widgets_child->remove = parents_child->remove; + if (!widgets_child->get_children) + widgets_child->get_children = parents_child->get_children; + if (!widgets_child->get_all_children) + widgets_child->get_all_children = parents_child->get_all_children; + if (!widgets_child->set_property) + widgets_child->set_property = parents_child->set_property; + if (!widgets_child->get_property) + widgets_child->get_property = parents_child->get_property; + if (!widgets_child->fill_empty) + widgets_child->fill_empty = parents_child->fill_empty; + if (!widgets_child->replace_child) + widgets_child->replace_child = parents_child->replace_child; + + glade_widget_class_merge_properties + (&widgets_child->properties, parents_child->properties); +} + +static void +glade_widget_class_merge_children (GList **widget_children, + GList *parent_children) +{ + GList *list; + GList *list2; + + for (list = parent_children; list && list->data; list = list->next) + { + GladeSupportedChild *parents_child = list->data; + GladeSupportedChild *widgets_child = NULL; + + for (list2 = *widget_children; list2 && list2->data; list2 = list2->next) + { + widgets_child = list2->data; + if (widgets_child->type == parents_child->type) + break; + } + + /* if not found, prepend a clone of the parent's one; if found + * but the parent one was modified (and not the child one) + * substitute it. + */ + if (!list2) + { + *widget_children = + g_list_prepend (*widget_children, + glade_widget_class_clone_child (parents_child)); + } + else + { + glade_widget_class_merge_child (widgets_child, parents_child); + } + } +} + + /** * glade_widget_class_merge: * @widget_class: main class. @@ -519,26 +692,22 @@ glade_widget_class_merge (GladeWidgetClass *widget_class, g_return_if_fail (GLADE_IS_WIDGET_CLASS (widget_class)); g_return_if_fail (GLADE_IS_WIDGET_CLASS (parent_class)); - if (widget_class->replace_child == NULL) - widget_class->replace_child = parent_class->replace_child; - - if (widget_class->pre_create_function == NULL) - widget_class->pre_create_function = parent_class->pre_create_function; - if (widget_class->post_create_function == NULL) widget_class->post_create_function = parent_class->post_create_function; - if (widget_class->fill_empty == NULL) - widget_class->fill_empty = parent_class->fill_empty; + if (widget_class->get_internal_child == NULL) + widget_class->get_internal_child = parent_class->get_internal_child; if (widget_class->child_property_applies == NULL) widget_class->child_property_applies = parent_class->child_property_applies; - /* merge the parent's properties & child-properties */ + /* merge the parent's properties */ glade_widget_class_merge_properties (&widget_class->properties, parent_class->properties); - glade_widget_class_merge_properties - (&widget_class->child_properties, parent_class->child_properties); + + /* merge the parent's supported children */ + glade_widget_class_merge_children + (&widget_class->children, parent_class->children); } /** @@ -665,25 +834,16 @@ glade_widget_class_new (const char *name, widget_class->name = g_strdup (name); widget_class->in_palette = generic_name ? TRUE : FALSE; - /* we can't just call g_type_from_name (name) to get the type, because - * that only works for registered types, and the only way to register the - * type is to call foo_bar_get_type() */ - init_function_name = glade_util_compose_get_type_func (widget_class->name); - if (!init_function_name) - { - g_warning (_("Not enough memory.")); - goto lblError; - } - - widget_class->type = glade_util_get_type_from_name (init_function_name); + widget_class->type = glade_util_get_type_from_name (widget_class->name); if (widget_class->type == 0) goto lblError; widget_class->properties = glade_widget_class_list_properties (widget_class); - widget_class->child_properties = glade_widget_class_list_child_properties (widget_class); - widget_class->signals = glade_widget_class_list_signals (widget_class); + widget_class->signals = glade_widget_class_list_signals (widget_class); + widget_class->children = glade_widget_class_list_children (widget_class); + widget_class->icon = glade_widget_class_create_icon (widget_class); + widget_class->child_property_applies = glade_widget_class_direct_children; - widget_class->icon = glade_widget_class_create_icon (widget_class); g_free (init_function_name); @@ -761,15 +921,28 @@ glade_widget_class_get_type (GladeWidgetClass *widget) GladePropertyClass * glade_widget_class_get_property_class (GladeWidgetClass *class, const gchar *name) { - GList *list; + GList *list, *l; GladePropertyClass *pclass; - for (list = class->properties; list; list = list->next) + for (list = class->properties; list && list->data; list = list->next) { pclass = list->data; if (strcmp (pclass->id, name) == 0) return pclass; } + + for (list = class->children; list && list->data; list = list->next) + { + GladeSupportedChild *support = list->data; + + for (l = support->properties; l && l->data; l = l->next) + { + pclass = l->data; + if (strcmp (pclass->id, name) == 0) + return pclass; + } + } + return NULL; } @@ -829,20 +1002,212 @@ glade_widget_class_dump_param_specs (GladeWidgetClass *class) } /** - * glade_widget_class_is: + * glade_widget_class_get_child_support: * @class: a #GladeWidgetClass - * @name: a string + * @child_type: a #GType + * + * Returns: The #GladeSupportedChild object appropriate to use for + * container vfuncs for this child_type if this child type is supported, + * otherwise NULL. * - * Returns: %TRUE if @class is named @name, %FALSE otherwise */ -gboolean -glade_widget_class_is (GladeWidgetClass *class, const gchar *name) +GladeSupportedChild * +glade_widget_class_get_child_support (GladeWidgetClass *class, + GType child_type) { - g_return_val_if_fail (GLADE_IS_WIDGET_CLASS (class), FALSE); - g_return_val_if_fail (name != NULL, FALSE); + GList *list; + GladeSupportedChild *child, *ret = NULL; - if (strcmp (class->name, name) == 0) - return TRUE; + for (list = class->children; list && list->data; list = list->next) + { + child = list->data; + if (g_type_is_a (child_type, child->type)) + { + if (ret == NULL) + ret = child; + else if (g_type_depth (ret->type) < + g_type_depth (child->type)) + ret = child; + } + } + return ret; +} + + +void +glade_widget_class_container_add (GladeWidgetClass *class, + GObject *container, + GObject *child) +{ + GladeSupportedChild *support; + + if ((support = + glade_widget_class_get_child_support (class, G_OBJECT_TYPE (child))) != NULL) + { + if (support->add) + support->add (container, child); + else + g_warning ("No add support for type %s in %s", + g_type_name (support->type), + class->name); + } + else + g_warning ("No support for type %s in %s", + g_type_name (G_OBJECT_TYPE (child)), + class->name); +} +void +glade_widget_class_container_remove (GladeWidgetClass *class, + GObject *container, + GObject *child) +{ + GladeSupportedChild *support; + + if ((support = + glade_widget_class_get_child_support (class, G_OBJECT_TYPE (child))) != NULL) + { + if (support->remove) + support->remove (container, child); + else + g_warning ("No remove support for type %s in %s", + g_type_name (support->type), + class->name); + } + else + g_warning ("No support for type %s in %s", + g_type_name (G_OBJECT_TYPE (child)), + class->name); +} + +GList * +glade_widget_class_container_get_children (GladeWidgetClass *class, + GObject *container) +{ + GList *list, *children = NULL; + + for (list = class->children; list && list->data; list = list->next) + { + GladeSupportedChild *support = list->data; + if (support->get_children) + children = g_list_concat (children, support->get_children (container)); + } + return children; +} + +GList * +glade_widget_class_container_get_all_children (GladeWidgetClass *class, + GObject *container) +{ + GList *list, *children = NULL; + + for (list = class->children; list && list->data; list = list->next) + { + GladeSupportedChild *support = list->data; + if (support->get_all_children) + children = g_list_concat (children, + support->get_all_children (container)); + } + return children; +} + +void +glade_widget_class_container_set_property (GladeWidgetClass *class, + GObject *container, + GObject *child, + const gchar *property_name, + const GValue *value) +{ + GladeSupportedChild *support; + + if ((support = + glade_widget_class_get_child_support (class, G_OBJECT_TYPE (child))) != NULL) + { + if (support->set_property) + support->set_property (container, child, + property_name, value); + else + g_warning ("No set_property support for type %s in %s", + g_type_name (support->type), class->name); + } + else + g_warning ("No support for type %s in %s", + g_type_name (G_OBJECT_TYPE (child)), + class->name); +} + + +void +glade_widget_class_container_get_property (GladeWidgetClass *class, + GObject *container, + GObject *child, + const gchar *property_name, + GValue *value) +{ + GladeSupportedChild *support; + + if ((support = + glade_widget_class_get_child_support (class, G_OBJECT_TYPE (child))) != NULL) + { + if (support->get_property) + support->get_property (container, child, + property_name, value); + else + g_warning ("No get_property support for type %s in %s", + g_type_name (support->type), class->name); + } + else + g_warning ("No support for type %s in %s", + g_type_name (G_OBJECT_TYPE (child)), + class->name); +} + +void +glade_widget_class_container_fill_empty (GladeWidgetClass *class, + GObject *container) +{ + GladeSupportedChild *support; + GList *list; + + for (list = class->children; list && list->data; list = list->next) + { + support = list->data; + if (support->fill_empty) + support->fill_empty (container); + } +} + +void +glade_widget_class_container_replace_child (GladeWidgetClass *class, + GObject *container, + GObject *old, + GObject *new) +{ + GladeSupportedChild *support; + + if ((support = + glade_widget_class_get_child_support (class, G_OBJECT_TYPE (old))) != NULL) + { + if (support->replace_child) + support->replace_child (container, old, new); + else + g_warning ("No replace_child support for type %s in %s", + g_type_name (support->type), class->name); + } + else + g_warning ("No support for type %s in %s", + g_type_name (G_OBJECT_TYPE (old)), class->name); +} + +gboolean +glade_widget_class_contains_non_widgets (GladeWidgetClass *class) +{ + GList *list; + for (list = class->children; list && list->data; list = list->next) + { + GladeSupportedChild *support = list->data; + if (!g_type_is_a (support->type, GTK_TYPE_WIDGET)) + return TRUE; + } return FALSE; } diff --git a/src/glade-widget-class.h b/src/glade-widget-class.h index e6ce5008..3ca1cdb3 100644 --- a/src/glade-widget-class.h +++ b/src/glade-widget-class.h @@ -13,6 +13,27 @@ G_BEGIN_DECLS #define GLADE_WIDGET_CLASS(gwc) ((GladeWidgetClass *) gwc) #define GLADE_IS_WIDGET_CLASS(gwc) (gwc != NULL) +typedef struct _GladeSupportedChild GladeSupportedChild; + + +typedef void (* GladeChildSetPropertyFunc) (GObject *container, + GObject *child, + const gchar *property_name, + const GValue *value); + +typedef void (* GladeChildGetPropertyFunc) (GObject *container, + GObject *child, + const gchar *property_name, + GValue *value); + +typedef GList *(* GladeGetChildrenFunc) (GObject *container); + +typedef void (* GladeAddChildFunc) (GObject *parent, + GObject *child); +typedef void (* GladeRemoveChildFunc) (GObject *parent, + GObject *child); + + /* GladeWidgetClass contains all the information we need regarding an widget * type. It is also used to store information that has been loaded to memory * for that object like the icon/mask. @@ -29,6 +50,7 @@ struct _GladeWidgetClass * example "button" so that we generate button1, * button2, buttonX .. */ + gchar *palette_name; /* Name used in the palette */ GList *properties; /* List of GladePropertyClass objects. @@ -41,16 +63,7 @@ struct _GladeWidgetClass GList *signals; /* List of GladeWidgetClassSignal objects */ - GList *child_properties; /* List of GladePropertyClass objects - * representing child_properties of a - * GtkContainer (the list is empty if the - * class isn't a container). - * Note that the actual GladeProperty - * corresponding to each class end up - * in the packing_properties list of - * each _child_ of the container and thus - * are edited when the _child_ is selected. - */ + GList *children; /* List of GladeSupportedChild objects */ GModule *module; /* Module with the (optional) special functions * needed for placeholder_replace, post_create_function @@ -60,39 +73,59 @@ struct _GladeWidgetClass gboolean in_palette; - /* This method replaces a child widget with another one: it's used to replace - * a placeholder with a widget and viceversa. - */ - void (*replace_child) (GtkWidget *current, - GtkWidget *new, - GtkWidget *container); - /* Executed after widget creation: it takes care of creating the * GladeWidgets associated with internal children. It's also the place * to set sane defaults, e.g. set the size of a window. */ - void (*post_create_function) (GObject *gobject); - - /* Executed before setting the properties of the widget to its initial - * value as specified in the xml file */ - void (*pre_create_function) (GObject *gobject); - - /* If the widget is a container, this method takes care of adding the - * needed placeholders. - */ - void (*fill_empty) (GtkWidget *widget); + void (*post_create_function) (GObject *gobject); /* Retrieves the the internal child of the given name. */ - void (*get_internal_child) (GtkWidget *parent, - const gchar *name, - GtkWidget **child); + void (*get_internal_child) (GObject *parent, + const gchar *name, + GObject **child); /* Is property_class of ancestor applicable to the widget? Usually property_class only * applies to direct children of a given ancestor */ gboolean (*child_property_applies) (GtkWidget *ancestor, GtkWidget *widget, - const char *property_id); + const gchar *property_id); +}; + +struct _GladeSupportedChild +{ + GType type; /* This supported child type */ + + GList *properties; /* List of GladePropertyClass objects representing + * child_properties of a container (the list is empty if + * this container has no child_properties) + * Note that the actual GladeProperty corresponding to + * each class end up in the packing_properties list of + * each _child_ of the container and thus are edited + * when the _child_ is selected. + */ + + GladeAddChildFunc add; /* Adds a new child of this type */ + GladeRemoveChildFunc remove; /* Removes a child from the container */ + GladeGetChildrenFunc get_children; /* Returns a list of children for this + * type, not including internals + */ + GladeGetChildrenFunc get_all_children; /* Returns a list of children of this + * type, including internals + */ + + GladeChildSetPropertyFunc set_property; /* Sets/Gets a packing property */ + GladeChildGetPropertyFunc get_property; /* for this child */ + + void (* fill_empty) (GObject *container); /* Used for placeholders in + * GtkContainers */ + + void (* replace_child) (GObject *container, /* This method replaces a */ + GObject *old, /* child widget with */ + GObject *new); /* another one: it's used to + * replace a placeholder with + * a widget and viceversa. + */ }; @@ -107,21 +140,48 @@ struct _GladeWidgetClassSignal }; -GladeWidgetClass *glade_widget_class_new (const char *name, const char *generic_name, const char *palette_name, const char *base_filename, const char *base_library); -GladeWidgetClass *glade_widget_class_new_from_node (GladeXmlNode *node); -void glade_widget_class_free (GladeWidgetClass *widget_class); -GladeWidgetClass *glade_widget_class_get_by_name (const char *name); - -const gchar *glade_widget_class_get_name (GladeWidgetClass *class); -GType glade_widget_class_get_type (GladeWidgetClass *class); -gboolean glade_widget_class_has_queries (GladeWidgetClass *class); - -gboolean glade_widget_class_is (GladeWidgetClass *class, const char *name); - -void glade_widget_class_dump_param_specs (GladeWidgetClass *class); -GladePropertyClass *glade_widget_class_get_property_class (GladeWidgetClass *class, - const gchar *name); - +GladeWidgetClass *glade_widget_class_new (const char *name, + const char *generic_name, + const char *palette_name, + const char *base_filename, + const char *base_library); +GladeWidgetClass *glade_widget_class_new_from_node (GladeXmlNode *node); +void glade_widget_class_free (GladeWidgetClass *widget_class); +GladeWidgetClass *glade_widget_class_get_by_name (const char *name); +GType glade_widget_class_get_type (GladeWidgetClass *class); +void glade_widget_class_dump_param_specs (GladeWidgetClass *class); +GladePropertyClass *glade_widget_class_get_property_class (GladeWidgetClass *class, + const gchar *name); +GladeSupportedChild *glade_widget_class_get_child_support (GladeWidgetClass *class, + GType child_type); + +void glade_widget_class_container_add (GladeWidgetClass *class, + GObject *container, + GObject *child); +void glade_widget_class_container_remove (GladeWidgetClass *class, + GObject *container, + GObject *child); +GList *glade_widget_class_container_get_children (GladeWidgetClass *class, + GObject *container); +GList *glade_widget_class_container_get_all_children (GladeWidgetClass *class, + GObject *container); +void glade_widget_class_container_set_property (GladeWidgetClass *class, + GObject *container, + GObject *child, + const gchar *property_name, + const GValue *value); +void glade_widget_class_container_get_property (GladeWidgetClass *class, + GObject *container, + GObject *child, + const gchar *property_name, + GValue *value); +void glade_widget_class_container_fill_empty (GladeWidgetClass *class, + GObject *container); +void glade_widget_class_container_replace_child (GladeWidgetClass *class, + GObject *container, + GObject *old, + GObject *new); +gboolean glade_widget_class_contains_non_widgets (GladeWidgetClass *class); G_END_DECLS diff --git a/src/glade-widget.c b/src/glade-widget.c index 986e3ff6..17bb33fd 100644 --- a/src/glade-widget.c +++ b/src/glade-widget.c @@ -51,6 +51,8 @@ static void glade_widget_get_real_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void glade_widget_set_properties (GladeWidget *widget, + GList *properties); static void glade_widget_set_class (GladeWidget *widget, GladeWidgetClass *klass); static void glade_widget_real_add_signal_handler (GladeWidget *widget, @@ -76,9 +78,10 @@ enum PROP_0, PROP_NAME, PROP_INTERNAL, - PROP_WIDGET, + PROP_OBJECT, PROP_CLASS, - PROP_PROJECT + PROP_PROJECT, + PROP_PROPERTIES }; static guint glade_widget_signals[LAST_SIGNAL] = {0}; @@ -150,10 +153,10 @@ glade_widget_class_init (GladeWidgetKlass *klass) G_PARAM_CONSTRUCT)); g_object_class_install_property - (object_class, PROP_WIDGET, - g_param_spec_object ("widget", _("Widget"), - _("The gtk+ widget associated"), - GTK_TYPE_WIDGET, + (object_class, PROP_OBJECT, + g_param_spec_object ("object", _("Object"), + _("The object associated"), + G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); @@ -174,6 +177,16 @@ glade_widget_class_init (GladeWidgetKlass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property + (object_class, PROP_PROPERTIES, + g_param_spec_pointer ("properties", _("Properties"), + _("A list of GladeProperties"), + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + + + glade_widget_signals[ADD_SIGNAL_HANDLER] = g_signal_new ("add_signal_handler", G_TYPE_FROM_CLASS (object_class), @@ -232,7 +245,7 @@ glade_widget_init (GladeWidget *widget) widget->project = NULL; widget->name = NULL; widget->internal = NULL; - widget->widget = NULL; + widget->object = NULL; widget->properties = NULL; widget->packing_properties = NULL; widget->signals = g_hash_table_new_full @@ -247,15 +260,18 @@ glade_widget_debug_real (GladeWidget *widget, int indent) g_print ("%*sGladeWidget at %p\n", indent, "", widget); g_print ("%*sname = [%s]\n", indent, "", widget->name ? widget->name : "-"); g_print ("%*sinternal = [%s]\n", indent, "", widget->internal ? widget->internal : "-"); - g_print ("%*sgtkwidget = %p [%s]\n", - indent, "", widget->widget, G_OBJECT_TYPE_NAME (widget->widget)); - g_print ("%*sgtkwidget->parent = %p\n", indent, "", gtk_widget_get_parent (widget->widget)); - if (GTK_IS_CONTAINER (widget->widget)) { + g_print ("%*sgobject = %p [%s]\n", + indent, "", widget->object, G_OBJECT_TYPE_NAME (widget->object)); + if (GTK_IS_WIDGET (widget->object)) + g_print ("%*sgtkwidget->parent = %p\n", indent, "", + gtk_widget_get_parent (GTK_WIDGET(widget->object))); + if (GTK_IS_CONTAINER (widget->object)) { GList *children, *l; - children = glade_util_container_get_all_children (GTK_CONTAINER (widget->widget)); + children = glade_util_container_get_all_children + (GTK_CONTAINER (widget->object)); for (l = children; l; l = l->next) { GtkWidget *widget_gtk = GTK_WIDGET (l->data); - GladeWidget *widget = glade_widget_get_from_gtk_widget (widget_gtk); + GladeWidget *widget = glade_widget_get_from_gobject (widget_gtk); if (widget) { glade_widget_debug_real (widget, indent + 2); } else if (GLADE_IS_PLACEHOLDER (widget_gtk)) { @@ -329,6 +345,53 @@ glade_widget_sync_custom_props (GladeWidget *widget) } } +static void +glade_widget_copy_props (GladeWidget *widget, + GladeWidget *template) +{ + GList *l; + for (l = widget->properties; l && l->data; l = l->next) + { + GladeProperty *dup_prop = GLADE_PROPERTY(l->data); + GladeProperty *orig_prop = + glade_widget_get_property (template, dup_prop->class->id); + glade_property_set (dup_prop, orig_prop->value); + } +} + +static GList * +glade_widget_dup_properties (GList *template_props) +{ + GList *list, *properties = NULL; + + for (list = template_props; list && list->data; list = list->next) + { + GladeProperty *prop = list->data; + properties = g_list_prepend (properties, glade_property_dup (prop, NULL)); + } + return g_list_reverse (properties); +} + +static void +glade_widget_fill_all_empty (GladeWidget *widget) +{ + GList *children, *list; + + if ((children = + glade_widget_class_container_get_children (widget->widget_class, + widget->object)) != NULL) + { + for (list = children; list && list->data; list = list->next) + { + GladeWidget *child_widget = + glade_widget_get_from_gobject (G_OBJECT (list->data)); + if (child_widget) + glade_widget_fill_all_empty (child_widget); + } + } + glade_widget_class_container_fill_empty (widget->widget_class, widget->object); +} + /** * glade_widget_build_object: * @klass: a #GladeWidgetClass @@ -432,22 +495,35 @@ glade_widget_build_object (GladeWidgetClass *klass, GladeWidget *widget) static GladeWidget * glade_widget_internal_new (GladeWidgetClass *klass, GladeProject *project, GladeWidget *template) { - GObject *widget; + GObject *object; GObject *glade_widget; - gchar *widget_name; - - widget = glade_widget_build_object(klass, template); + GList *properties; + gchar *widget_name; - if (klass->pre_create_function) - klass->pre_create_function (G_OBJECT (widget)); - + object = glade_widget_build_object(klass, template); widget_name = glade_project_new_widget_name (project, klass->generic_name); - glade_widget = g_object_new (GLADE_TYPE_WIDGET, - "class", klass, - "project", project, - "name", widget_name, - "widget", widget, - NULL); + + if (template) + { + properties = glade_widget_dup_properties (template->properties); + glade_widget = g_object_new (GLADE_TYPE_WIDGET, + "properties", properties, + "class", klass, + "project", project, + "name", widget_name, + "object", object, + NULL); + } + else + { + glade_widget = g_object_new (GLADE_TYPE_WIDGET, + "class", klass, + "project", project, + "name", widget_name, + "object", object, + NULL); + } + g_free (widget_name); return (GladeWidget *) glade_widget; @@ -469,6 +545,8 @@ glade_widget_new (GladeWidgetClass *klass, GladeProject *project) if ((widget = glade_widget_internal_new (klass, project, NULL)) != NULL) { + glade_widget_class_container_fill_empty (klass, widget->object); + if (widget->query_user) { GladeProjectWindow *gpw = glade_project_window_get (); @@ -484,56 +562,93 @@ glade_widget_new (GladeWidgetClass *klass, GladeProject *project) } /** - * glade_widget_dup: + * glade_widget_dup_internal: * @widget: a #GladeWidget * * TODO: write me * * Returns: */ -GladeWidget * -glade_widget_dup (GladeWidget *template) +static GladeWidget * +glade_widget_dup_internal (GladeWidget *template) { GladeWidget *gwidget; - GList *l, *children; + GList *list, *children; g_return_val_if_fail (template != NULL && GLADE_IS_WIDGET(template), NULL); gwidget = glade_widget_internal_new (template->widget_class, template->project, template); - - if (GTK_IS_CONTAINER(template->widget)) + if ((children = + glade_widget_class_container_get_all_children (template->widget_class, + template->object)) != NULL) { - children = gtk_container_get_children(GTK_CONTAINER(template->widget)); - for (l = children; l && l->data; l = l->next) + for (list = children; list && list->data; list = list->next) { - GtkWidget *child_widget = GTK_WIDGET(l->data); - GladeWidget *child_gwidget; - if ((child_gwidget = - glade_widget_get_from_gtk_widget(child_widget)) != NULL) + GObject *child = G_OBJECT (list->data); + GladeWidget *child_gwidget, *child_dup; + + if ((child_gwidget = glade_widget_get_from_gobject (child)) == NULL) + continue; + + if (child_gwidget->internal == NULL) { - GladeWidget *child_dup = - glade_widget_dup(child_gwidget); + child_dup = glade_widget_dup_internal (child_gwidget); + + child_dup->parent = gwidget; - gtk_container_add(GTK_CONTAINER(gwidget->widget), - child_dup->widget); + glade_widget_class_container_add (gwidget->widget_class, + gwidget->object, + child_dup->object); glade_widget_copy_packing_props (gwidget, child_dup, child_gwidget); + } + else if (gwidget->widget_class->get_internal_child) + { + GObject *internal_object = NULL; + gwidget->widget_class->get_internal_child + (gwidget->object, + child_gwidget->internal, + &internal_object); + + if ((child_dup = glade_widget_get_from_gobject + (internal_object)) != NULL) + { + glade_widget_copy_props (child_dup, + child_gwidget); + + /* If custom properties are still at thier + * default value, they need to be synced. + */ + glade_widget_sync_custom_props (child_dup); + } } } + g_list_free (children); } - + glade_widget_copy_custom_props (gwidget, template); - gtk_widget_show_all (gwidget->widget); + if (GTK_IS_WIDGET (gwidget->object) && !GTK_WIDGET_TOPLEVEL(gwidget->object)) + gtk_widget_show_all (GTK_WIDGET (gwidget->object)); return gwidget; } +GladeWidget * +glade_widget_dup (GladeWidget *template) +{ + GladeWidget *widget = glade_widget_dup_internal (template); + if (widget) + glade_widget_fill_all_empty (widget); + return widget; +} + + /** * glade_widget_rebuild: * @glade_widget: a #GladeWidget @@ -546,27 +661,34 @@ glade_widget_dup (GladeWidget *template) void glade_widget_rebuild (GladeWidget *glade_widget) { - GtkWidget *new_widget, *old_widget; + GObject *new_object, *old_object; GladeWidgetClass *klass = glade_widget->widget_class; /* Hold a reference to the old widget while we transport properties * and children from it */ - new_widget = GTK_WIDGET(glade_widget_build_object(klass, glade_widget)); - old_widget = g_object_ref(G_OBJECT(glade_widget_get_widget(glade_widget))); + new_object = glade_widget_build_object(klass, glade_widget); + old_object = g_object_ref(glade_widget_get_object(glade_widget)); - glade_widget_set_widget(glade_widget, new_widget); + glade_widget_set_object(glade_widget, new_object); + glade_widget_class_container_fill_empty (klass, new_object); + /* Custom properties aren't transfered in build_object, since build_object * is only concerned with object creation. */ glade_widget_sync_custom_props (glade_widget); - /* Must use gtk_widget_destroy here for cases like dialogs and toplevels - * (otherwise I'd prefer g_object_unref() ) - */ - gtk_widget_destroy(old_widget); - gtk_widget_show_all(new_widget); + if (g_type_is_a (klass->type, GTK_TYPE_WIDGET)) + { + /* Must use gtk_widget_destroy here for cases like dialogs and toplevels + * (otherwise I'd prefer g_object_unref() ) + */ + gtk_widget_destroy (GTK_WIDGET(old_object)); + gtk_widget_show_all (GTK_WIDGET(new_object)); + } + else + g_object_unref (old_object); } @@ -584,7 +706,7 @@ glade_widget_rebuild (GladeWidget *glade_widget) GladeWidget * glade_widget_new_for_internal_child (GladeWidgetClass *klass, GladeWidget *parent, - GtkWidget *internal_widget, + GObject *internal_object, const gchar *internal_name) { GladeProject *project = glade_widget_get_project (parent); @@ -594,8 +716,11 @@ glade_widget_new_for_internal_child (GladeWidgetClass *klass, "project", project, "name", widget_name, "internal", internal_name, - "widget", internal_widget, NULL); + "object", internal_object, NULL); g_free (widget_name); + + widget->parent = parent; + glade_widget_set_packing_properties (widget, parent); return widget; } @@ -627,15 +752,13 @@ glade_widget_dispose (GObject *object) g_return_if_fail (GLADE_IS_WIDGET (object)); - if (widget->project) { - g_object_unref (widget->project); - widget->project = NULL; - } + if (widget->project) + widget->project = + (g_object_unref (widget->project), NULL); - if (widget->widget) { - g_object_unref (widget->widget); - widget->widget = NULL; - } + if (widget->object) + widget->object = + (g_object_unref (widget->object), NULL); if (widget->properties) { g_list_foreach (widget->properties, (GFunc) glade_property_free, NULL); @@ -720,9 +843,8 @@ glade_widget_set_real_property (GObject *object, case PROP_INTERNAL: glade_widget_set_internal (widget, g_value_get_string (value)); break; - case PROP_WIDGET: - glade_widget_set_widget (widget, GTK_WIDGET - (g_value_get_object (value))); + case PROP_OBJECT: + glade_widget_set_object (widget, g_value_get_object (value)); break; case PROP_PROJECT: glade_widget_set_project (widget, GLADE_PROJECT @@ -732,6 +854,9 @@ glade_widget_set_real_property (GObject *object, glade_widget_set_class (widget, GLADE_WIDGET_CLASS (g_value_get_pointer (value))); break; + case PROP_PROPERTIES: + glade_widget_set_properties (widget, (GList *)g_value_get_pointer (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -762,9 +887,11 @@ glade_widget_get_real_property (GObject *object, case PROP_PROJECT: g_value_set_object (value, widget->project); break; - case PROP_WIDGET: - g_value_set_object (value, widget->widget); + case PROP_OBJECT: + g_value_set_object (value, widget->object); break; + case PROP_PROPERTIES: + g_value_set_pointer (value, widget->properties); default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -836,6 +963,28 @@ glade_widget_get_internal (GladeWidget *widget) } static void +glade_widget_set_properties (GladeWidget *widget, GList *properties) +{ + GList *list; + + /* "properties" has to be specified before "class" on the g_object_new line. + */ + if (widget->properties == NULL) + { + widget->properties = properties; + for (list = properties; list; list = list->next) + { + GladeProperty *property = list->data; + property->widget = widget; + if (property->class->query) + { + widget->query_user = TRUE; + } + } + } +} + +static void glade_widget_set_class (GladeWidget *widget, GladeWidgetClass *klass) { GladePropertyClass *property_class; @@ -847,24 +996,26 @@ glade_widget_set_class (GladeWidget *widget, GladeWidgetClass *klass) /* calling set_class out of the constructor? */ g_return_if_fail (widget->widget_class == NULL); - // g_object_ref (klass); TODO, GladeWidgetClass is not a GObject widget->widget_class = klass; - for (list = klass->properties; list; list = list->next) + if (!widget->properties) { - property_class = GLADE_PROPERTY_CLASS(list->data); - property = glade_property_new (property_class, widget); - if (!property) { - g_print ("Failed to create [%s] property.\n", - property_class->id); - continue; - } + for (list = klass->properties; list; list = list->next) + { + property_class = GLADE_PROPERTY_CLASS(list->data); + property = glade_property_new (property_class, widget, NULL); + if (!property) { + g_print ("Failed to create [%s] property.\n", + property_class->id); + continue; + } - widget->properties = g_list_prepend (widget->properties, property); - if (property_class->query) widget->query_user = TRUE; + widget->properties = g_list_prepend (widget->properties, property); + if (property_class->query) widget->query_user = TRUE; + } + widget->properties = g_list_reverse (widget->properties); } - widget->properties = g_list_reverse (widget->properties); } /** @@ -954,7 +1105,7 @@ glade_widget_popup_menu (GtkWidget *widget, gpointer unused_data) g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); - glade_widget = glade_widget_get_from_gtk_widget (widget); + glade_widget = glade_widget_get_from_gobject (widget); glade_popup_widget_pop (glade_widget, NULL); return TRUE; @@ -978,7 +1129,7 @@ glade_widget_find_inside_container (GtkWidget *widget, GladeFindInContainerData gtk_widget_translate_coordinates (data->toplevel, widget, data->x, data->y, &x, &y); if (x >= 0 && x < widget->allocation.width && y >= 0 && y < widget->allocation.height && - (glade_widget_get_from_gtk_widget (widget)) && GTK_WIDGET_MAPPED(widget)) + (glade_widget_get_from_gobject (widget)) && GTK_WIDGET_MAPPED(widget)) data->found = widget; } @@ -1000,9 +1151,9 @@ glade_widget_find_deepest_child_at_position (GtkContainer *toplevel, return glade_widget_find_deepest_child_at_position (toplevel, GTK_CONTAINER (data.found), top_x, top_y); else if (data.found) - return glade_widget_get_from_gtk_widget (data.found); + return glade_widget_get_from_gobject (data.found); else - return glade_widget_get_from_gtk_widget (container); + return glade_widget_get_from_gobject (container); } /** @@ -1045,7 +1196,7 @@ glade_widget_button_press (GtkWidget *widget, glade_widget = glade_widget_retrieve_from_position (widget, (int) (x + 0.5), (int) (y + 0.5)); - widget = glade_widget_get_widget (glade_widget); + widget = GTK_WIDGET (glade_widget_get_object (glade_widget)); /* make sure to grab focus, since we may stop default handlers */ if (GTK_WIDGET_CAN_FOCUS (widget) && !GTK_WIDGET_HAS_FOCUS (widget)) @@ -1060,10 +1211,10 @@ glade_widget_button_press (GtkWidget *widget, if (event->button == 1) { /* if it's already selected don't stop default handlers, e.g. toggle button */ - if (glade_util_has_nodes (widget)) + if (glade_util_has_selection (G_OBJECT(widget))) return FALSE; - glade_project_selection_set (glade_widget->project, widget, TRUE); + glade_project_selection_set (glade_widget->project, G_OBJECT(widget), TRUE); return TRUE; } @@ -1085,7 +1236,7 @@ glade_widget_key_press (GtkWidget *event_widget, g_return_val_if_fail (GTK_IS_WIDGET (event_widget), FALSE); - glade_widget = glade_widget_get_from_gtk_widget (event_widget); + glade_widget = glade_widget_get_from_gobject (event_widget); /* We will delete all the selected items */ if (event->keyval == GDK_Delete) @@ -1142,7 +1293,11 @@ glade_widget_connect_signal_handlers (GtkWidget *widget_gtk, gpointer data) GINT_TO_POINTER (1)); } - /* We also need to get expose events for any children. */ + /* We also need to get expose events for any children. + * Note that we are only interested in children returned through the + * standard GtkContainer interface, as this is stricktly Gtk+ stuff. + * (hence the absence of glade_widget_class_container_get_children () ) + */ if (GTK_IS_CONTAINER (widget_gtk)) { gtk_container_forall (GTK_CONTAINER (widget_gtk), glade_widget_connect_signal_handlers, @@ -1153,44 +1308,48 @@ glade_widget_connect_signal_handlers (GtkWidget *widget_gtk, gpointer data) /** * glade_widget_transport_children: * @gwidget: A #GladeWidget - * @from_container: A #GtkContainer - * @to_container: A #GtkContainer + * @from_container: A #GObject + * @to_container: A #GObject * * Transports all children from @from_container to @to_container * */ static void glade_widget_transport_children (GladeWidget *gwidget, - GtkContainer *from_container, - GtkContainer *to_container) + GObject *from_container, + GObject *to_container) { - GList *l, *children = - from_container ? gtk_container_get_children(from_container) : NULL; + GList *list, *children; - for (l = children; l && l->data; l = l->next) + if ((children = glade_widget_class_container_get_children (gwidget->widget_class, + from_container)) != NULL) { - GtkWidget *child = (GtkWidget *)l->data; - - /* If this widget is a container, all children get a temporary - * reference and are moved from the old container, to the new - * container and thier child properties are applied. - */ - g_object_ref(child); - gtk_container_remove(GTK_CONTAINER(from_container), child); - gtk_container_add(GTK_CONTAINER(to_container), child); - glade_widget_set_packing_properties - (glade_widget_get_from_gtk_widget (child), gwidget); - g_object_unref(child); - + for (list = children; list && list->data; list = list->next) + { + GObject *child = G_OBJECT(list->data); + + /* If this widget is a container, all children get a temporary + * reference and are moved from the old container, to the new + * container and thier child properties are applied. + */ + g_object_ref(child); + glade_widget_class_container_remove (gwidget->widget_class, + from_container, child); + glade_widget_class_container_add (gwidget->widget_class, + to_container, child); + glade_widget_set_packing_properties + (glade_widget_get_from_gobject (child), gwidget); + g_object_unref(child); + } + g_list_free (children); } - g_list_free(children); } /** * glade_widget_update_parent: * @widget: A #GladeWidget - * @old_widget: A #GtkWidget - * @new_widget: A #GtkWidget + * @old_object: A #GObject + * @new_object: A #GObject * * Finds @widget's parent #GladeWidget and calls the replace_child func * and takes care of packing @@ -1198,124 +1357,104 @@ glade_widget_transport_children (GladeWidget *gwidget, * Returns: whether this widget had a parent. */ static gboolean -glade_widget_update_parent(GladeWidget *gwidget, GtkWidget *old_widget, GtkWidget *new_widget) +glade_widget_update_parent(GladeWidget *parent, GObject *old_object, GObject *new_object) { - GladeWidget *parent; - - /* Take care of reparenting, if needed (i.e.: if not a GtkWindow) - */ - if (old_widget && (parent = glade_util_get_parent (old_widget)) != NULL) + if (old_object) { - if (parent->widget_class->replace_child) - { - if (old_widget) - parent->widget_class->replace_child - (old_widget, new_widget, - glade_widget_get_widget (parent)); + glade_widget_class_container_replace_child (parent->widget_class, + parent->object, + old_object, new_object); + + if (GLADE_IS_PLACEHOLDER(new_object) == FALSE) + glade_widget_set_packing_properties + (glade_widget_get_from_gobject (new_object), parent); - if (GLADE_IS_PLACEHOLDER(new_widget) == FALSE) - glade_widget_set_packing_properties (gwidget, parent); - } - else - g_warning ("Unable to set packing properties on new instance: replace " - "function has not been implemented for \"%s\"\n", - parent->widget_class->name); return TRUE; } return FALSE; } /** - * glade_widget_set_widget: + * glade_widget_set_object: * @gwidget: * @new_widget: * * TODO: write me */ void -glade_widget_set_widget (GladeWidget *gwidget, GtkWidget *new_widget) +glade_widget_set_object (GladeWidget *gwidget, GObject *new_object) { GladeWidgetClass *klass; - GtkWidget *old_widget; + GladeWidget *parent; + GObject *old_object; g_return_if_fail (GLADE_IS_WIDGET (gwidget)); - g_return_if_fail (GTK_IS_WIDGET (new_widget)); - g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (new_widget), + g_return_if_fail (G_IS_OBJECT (new_object)); + g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (new_object), gwidget->widget_class->type)); klass = gwidget->widget_class; - old_widget = gwidget->widget; + old_object = gwidget->object; /* Add internal reference to new widget */ - gwidget->widget = g_object_ref (G_OBJECT(new_widget)); - g_object_set_data (G_OBJECT (new_widget), "GladeWidgetDataTag", gwidget); + gwidget->object = g_object_ref (G_OBJECT(new_object)); + g_object_set_data (G_OBJECT (new_object), "GladeWidgetDataTag", gwidget); if (gwidget->internal == NULL) { /* Call custom notification of widget creation in plugin */ if (klass->post_create_function) - klass->post_create_function (G_OBJECT(new_widget)); + klass->post_create_function (G_OBJECT(new_object)); - /* Take care of events and toolkit signals. - */ - gtk_widget_add_events (new_widget, GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_KEY_PRESS_MASK); + if (g_type_is_a (gwidget->widget_class->type, GTK_TYPE_WIDGET)) + { + + /* Take care of events and toolkit signals. + */ + gtk_widget_add_events (GTK_WIDGET(new_object), + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_KEY_PRESS_MASK); - if (GTK_WIDGET_TOPLEVEL (new_widget)) - g_signal_connect (G_OBJECT (new_widget), "delete_event", - G_CALLBACK (gtk_widget_hide_on_delete), NULL); + if (GTK_WIDGET_TOPLEVEL (new_object)) + g_signal_connect (G_OBJECT (new_object), "delete_event", + G_CALLBACK (gtk_widget_hide_on_delete), NULL); - g_signal_connect (G_OBJECT (new_widget), "popup_menu", - G_CALLBACK (glade_widget_popup_menu), NULL); - g_signal_connect (G_OBJECT (new_widget), "key_press_event", - G_CALLBACK (glade_widget_key_press), NULL); + g_signal_connect (G_OBJECT (new_object), "popup_menu", + G_CALLBACK (glade_widget_popup_menu), NULL); + g_signal_connect (G_OBJECT (new_object), "key_press_event", + G_CALLBACK (glade_widget_key_press), NULL); - glade_widget_connect_signal_handlers (new_widget, NULL); - - /* Take care of reparenting and packing. - */ - if (glade_widget_update_parent(gwidget, old_widget, new_widget) == FALSE) - { - /* XXX We have to take care of GtkWindow positioning - * (in the case of parentless widgets) - */ + glade_widget_connect_signal_handlers (GTK_WIDGET(new_object), NULL); } + + if ((parent = glade_widget_get_parent (gwidget)) != NULL) + glade_widget_update_parent(parent, old_object, new_object); + } - if (GTK_IS_CONTAINER (new_widget) && - (GTK_IS_BIN(new_widget) == FALSE || GTK_BIN(new_widget)->child == NULL)) - glade_widget_transport_children (gwidget, - GTK_CONTAINER(old_widget), - GTK_CONTAINER(new_widget)); - - - /* Call fill empty function regardless of whether there were children before - * it is the plugin's responsability to check if it is empty or not. - */ - if (klass->fill_empty) - klass->fill_empty (new_widget); - + if (old_object) + glade_widget_transport_children (gwidget, old_object, new_object); /* Remove internal reference to old widget */ - if (old_widget) { - g_object_set_data (G_OBJECT (old_widget), "GladeWidgetDataTag", NULL); - g_object_unref (G_OBJECT (old_widget)); + if (old_object) { + g_object_set_data (G_OBJECT (old_object), "GladeWidgetDataTag", NULL); + g_object_unref (G_OBJECT (old_object)); } - g_object_notify (G_OBJECT (gwidget), "widget"); + g_object_notify (G_OBJECT (gwidget), "object"); } /** - * glade_widget_get_widget: + * glade_widget_get_object: * @widget: a #GladeWidget * - * Returns: the #GtkWidget associated with @widget + * Returns: the #GObject associated with @widget */ -GtkWidget * -glade_widget_get_widget (GladeWidget *widget) +GObject * +glade_widget_get_object (GladeWidget *widget) { g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL); - return widget->widget; + return widget->object; } static void @@ -1341,9 +1480,9 @@ glade_widget_real_add_signal_handler (GladeWidget *widget, GladeSignal *signal_h static void glade_widget_real_remove_signal_handler (GladeWidget *widget, GladeSignal *signal_handler) { - GPtrArray *signals; + GPtrArray *signals; GladeSignal *tmp_signal_handler; - size_t i; + gint i; g_return_if_fail (GLADE_IS_WIDGET (widget)); g_return_if_fail (GLADE_IS_SIGNAL (signal_handler)); @@ -1357,14 +1496,12 @@ glade_widget_real_remove_signal_handler (GladeWidget *widget, GladeSignal *signa { tmp_signal_handler = g_ptr_array_index (signals, i); if (glade_signal_equal (tmp_signal_handler, signal_handler)) + { + glade_signal_free (tmp_signal_handler); + g_ptr_array_remove_index (signals, i); break; + } } - - /* trying to remove an inexistent signal? */ - g_assert(i != signals->len); - - glade_signal_free (tmp_signal_handler); - g_ptr_array_remove_index (signals, i); } static void @@ -1372,9 +1509,9 @@ glade_widget_real_change_signal_handler (GladeWidget *widget, GladeSignal *old_signal_handler, GladeSignal *new_signal_handler) { - GPtrArray *signals; + GPtrArray *signals; GladeSignal *tmp_signal_handler; - size_t i; + gint i; g_return_if_fail (GLADE_IS_WIDGET (widget)); g_return_if_fail (GLADE_IS_SIGNAL (old_signal_handler)); @@ -1382,6 +1519,7 @@ glade_widget_real_change_signal_handler (GladeWidget *widget, g_return_if_fail (strcmp (old_signal_handler->name, new_signal_handler->name) == 0); signals = glade_widget_list_signal_handlers (widget, old_signal_handler->name); + /* trying to remove an inexistent signal? */ g_assert (signals); @@ -1389,19 +1527,18 @@ glade_widget_real_change_signal_handler (GladeWidget *widget, { tmp_signal_handler = g_ptr_array_index (signals, i); if (glade_signal_equal (tmp_signal_handler, old_signal_handler)) + { + if (strcmp (old_signal_handler->handler, + new_signal_handler->handler) != 0) + { + g_free (tmp_signal_handler->handler); + tmp_signal_handler->handler = + g_strdup (new_signal_handler->handler); + } + tmp_signal_handler->after = new_signal_handler->after; break; + } } - - /* trying to remove an inexistent signal? */ - g_assert (i != signals->len); - - if (strcmp (old_signal_handler->handler, new_signal_handler->handler) != 0) - { - g_free (tmp_signal_handler->handler); - tmp_signal_handler->handler = g_strdup (new_signal_handler->handler); - } - - tmp_signal_handler->after = new_signal_handler->after; } GPtrArray * @@ -1412,76 +1549,36 @@ glade_widget_list_signal_handlers (GladeWidget *widget, } GladeWidget * -glade_widget_get_parent (GladeWidget *glade_widget) +glade_widget_get_parent (GladeWidget *widget) { - GladeWidget *parent = NULL; - GtkWidget *widget, *parent_widget; - - g_return_val_if_fail (GLADE_IS_WIDGET (glade_widget), NULL); - - widget = glade_widget_get_widget (glade_widget); - - if (GTK_WIDGET_TOPLEVEL (widget)) - return NULL; - - parent_widget = gtk_widget_get_parent (widget); - - parent = glade_widget_get_from_gtk_widget (parent_widget); - - return parent; + g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL); + return widget->parent; } /** - * Returns a list of GladeProperties from a list of - * GladePropertyClass. - * - * Note: The code #if 0'ed supposes that the widgets are chained, i.e. widget is - * already inside container, and container is inside its container, etc. until - * the toplevel. However that's false upon reading from a xml file. The code - * is only useful for "grand-child" properties, that are still not used, so - * we can by now let it #if 0'ed. + * Returns a list of GladeProperties from a list for the correct + * child type for this widget of this container. */ static GList * glade_widget_create_packing_properties (GladeWidget *container, GladeWidget *widget) { - GladePropertyClass *property_class; - GladeProperty *property; - GladeWidgetClass *container_class = glade_widget_get_class (container); - GList *list = container_class->child_properties; - GList *new_list = NULL; -#if 0 - GladeWidget *parent; - GList *ancestor_list; -#endif - - for (; list; list = list->next) - { - property_class = list->data; - -#if 0 - if (!container_class->child_property_applies - (container->widget, widget->widget, property_class->id)) - continue; -#endif - - property = glade_property_new (property_class, widget); - if (!property) - continue; - - new_list = g_list_prepend (new_list, property); - } - -#if 0 - new_list = g_list_reverse (new_list); - parent = glade_widget_get_parent (container); - if (parent != NULL) + GladeSupportedChild *support; + GladePropertyClass *property_class; + GladeProperty *property; + GList *list, *packing_props = NULL; + + if ((support = + glade_widget_class_get_child_support + (container->widget_class, widget->widget_class->type)) != NULL) { - ancestor_list = glade_widget_create_packing_properties (parent, widget); - new_list = g_list_concat (new_list, ancestor_list); + for (list = support->properties; list && list->data; list = list->next) + { + property_class = list->data; + property = glade_property_new (property_class, widget, NULL); + packing_props = g_list_prepend (packing_props, property); + } } -#endif - - return new_list; + return packing_props; } /** @@ -1498,69 +1595,69 @@ static void glade_widget_set_packing_properties (GladeWidget *widget, GladeWidget *container) { - GList *list; + GList *list; g_return_if_fail (GLADE_IS_WIDGET (widget)); g_return_if_fail (GLADE_IS_WIDGET (container)); - /* toplevels do not have packing properties, so should not be - * passed to this function. - */ - g_return_if_fail (!GTK_WIDGET_TOPLEVEL (widget->widget)); - g_list_foreach (widget->packing_properties, (GFunc) glade_property_free, NULL); g_list_free (widget->packing_properties); widget->packing_properties = glade_widget_create_packing_properties (container, widget); /* update the values of the properties to the ones we get from gtk */ - for (list = widget->packing_properties; list; list = list->next) + for (list = widget->packing_properties; + list && list->data; + list = list->next) { GladeProperty *property = list->data; - g_value_reset (property->value); - if (gtk_container_class_find_child_property - (G_OBJECT_GET_CLASS (container->widget), property->class->id)) - gtk_container_child_get_property (GTK_CONTAINER (container->widget), - widget->widget, - property->class->id, - property->value); + glade_widget_class_container_get_property (container->widget_class, + container->object, + widget->object, + property->class->id, + property->value); } } /** * glade_widget_replace: - * @old_widget: a #GtkWidget - * @new_widget: a #GtkWidget + * @old_object: a #GObject + * @new_object: a #GObject * - * Replaces a GtkWidget with another GtkWidget inside a GtkContainer. + * Replaces a GObject with another GObject inside a GObject which + * behaves as a container. * - * Note that both GtkWidgets must be owned by a GladeWidget. + * Note that both GObjects must be owned by a GladeWidget. */ void -glade_widget_replace (GtkWidget *old_widget, GtkWidget *new_widget) +glade_widget_replace (GladeWidget *parent, GObject *old_object, GObject *new_object) { GladeWidget *gnew_widget = NULL; GladeWidget *gold_widget = NULL; - GtkWidget *real_new_widget = new_widget; - GtkWidget *real_old_widget = old_widget; + GObject *real_new_object = new_object; + GObject *real_old_object = old_object; - g_return_if_fail (GTK_IS_WIDGET (old_widget)); - g_return_if_fail (GTK_IS_WIDGET (new_widget)); + g_return_if_fail (G_IS_OBJECT (old_object)); + g_return_if_fail (G_IS_OBJECT (new_object)); - gnew_widget = glade_widget_get_from_gtk_widget (new_widget); - gold_widget = glade_widget_get_from_gtk_widget (old_widget); + gnew_widget = glade_widget_get_from_gobject (new_object); + gold_widget = glade_widget_get_from_gobject (old_object); - if (gnew_widget) - real_new_widget = glade_widget_get_widget (gnew_widget); - if (gold_widget) - real_old_widget = glade_widget_get_widget (gold_widget); + if (gnew_widget) { + real_new_object = glade_widget_get_object (gnew_widget); + gnew_widget->parent = parent; + } + if (gold_widget) { + real_old_object = glade_widget_get_object (gold_widget); + gold_widget->parent = NULL; + } - glade_widget_update_parent(gnew_widget, real_old_widget, real_new_widget); + glade_widget_update_parent(parent, real_old_object, real_new_object); } /* XML Serialization */ static gboolean -glade_widget_write_child (GArray *children, GtkWidget *gtk_widget, GladeInterface *interface); +glade_widget_write_child (GArray *children, GObject *object, GladeInterface *interface); typedef struct _WriteSignalsContext { @@ -1572,8 +1669,8 @@ static void glade_widget_write_signals (gpointer key, gpointer value, gpointer user_data) { WriteSignalsContext *write_signals_context; - GPtrArray *signals; - size_t i; + GPtrArray *signals; + gint i; write_signals_context = (WriteSignalsContext *) user_data; signals = (GPtrArray *) value; @@ -1643,43 +1740,44 @@ glade_widget_write (GladeWidget *widget, GladeInterface *interface) g_array_free (write_signals_context.signals, FALSE); /* Children */ - if (GTK_IS_CONTAINER (widget->widget)) { - list = glade_util_container_get_all_children (GTK_CONTAINER (widget->widget)); - children = g_array_new (FALSE, FALSE, - sizeof (GladeChildInfo)); - for (; list; list = list->next) { - GtkWidget *child_widget; - child_widget = GTK_WIDGET (list->data); - glade_widget_write_child (children, - child_widget, - interface); - } - info->children = (GladeChildInfo *) children->data; + if ((list = + glade_widget_class_container_get_all_children (widget->widget_class, + widget->object)) != NULL) + { + children = g_array_new (FALSE, FALSE, sizeof (GladeChildInfo)); + while (list && list->data) + { + GObject *child = list->data; + glade_widget_write_child (children, child, interface); + list = list->next; + } + info->children = (GladeChildInfo *) children->data; info->n_children = children->len; + g_array_free (children, FALSE); + g_list_free (list); } - g_hash_table_insert(interface->names, info->name, info); return info; } gboolean -glade_widget_write_child (GArray *children, GtkWidget *gtk_widget, GladeInterface *interface) +glade_widget_write_child (GArray *children, GObject *object, GladeInterface *interface) { GladeChildInfo info = { 0 }; GladeWidget *child_widget; GList *list; GArray *props; - if (GLADE_IS_PLACEHOLDER (gtk_widget)) + /* if (GLADE_IS_PLACEHOLDER (gtk_widget)) { - /* g_array_append_val (children, info); */ + g_array_append_val (children, info); return TRUE; - } + } */ - child_widget = glade_widget_get_from_gtk_widget (gtk_widget); + child_widget = glade_widget_get_from_gobject (object); if (!child_widget) return FALSE; @@ -1714,38 +1812,62 @@ glade_widget_write_child (GArray *children, GtkWidget *gtk_widget, GladeInterfac return TRUE; } +static GValue * +glade_widget_value_from_prop_info (GladePropInfo *info, + GladeWidgetClass *class) +{ + GladePropertyClass *pclass; + GValue *gvalue = NULL; + gchar *id; + + g_return_val_if_fail (info != NULL, NULL); + + id = g_strdup (info->name); + glade_util_replace (id, '_', '-'); + + if (info->name && info->value && + (pclass = glade_widget_class_get_property_class (class, id)) != NULL) + gvalue = glade_property_class_make_gvalue_from_string (pclass, + info->value); + + g_free (id); + + return gvalue; +} + static gboolean glade_widget_apply_property_from_prop_info (GladePropInfo *info, - GladeWidget *widget, - gboolean packing) + GladeWidget *widget) { - GladeProperty *property; - GValue *gvalue; - gchar *id; + GladeProperty *property; + GladeWidgetClass *wclass; + GValue *gvalue; + gchar *id; g_return_val_if_fail (info != NULL, FALSE); g_return_val_if_fail (widget != NULL, FALSE); - if (!info->name || !info->value) - return FALSE; - id = g_strdup (info->name); - glade_util_replace (id, '_', '-'); property = glade_widget_get_property (widget, id); + g_free (id); + if (!property) + { return FALSE; + } - if (!strcmp(id, "use-underline") && !strcmp(widget->name, "btnExit")) - id = id; - - gvalue = glade_property_class_make_gvalue_from_string (property->class, info->value); - glade_property_set (property, gvalue); - - g_free (id); - g_value_unset (gvalue); - g_free (gvalue); + wclass = property->class->packing ? + widget->parent->widget_class : + widget->widget_class; + + if ((gvalue = glade_widget_value_from_prop_info (info, wclass)) != NULL) + { + glade_property_set (property, gvalue); + g_value_unset (gvalue); + g_free (gvalue); + } return TRUE; } @@ -1755,7 +1877,9 @@ glade_widget_new_child_from_child_info (GladeChildInfo *info, GladeWidget *parent); static void -glade_widget_fill_from_widget_info (GladeWidgetInfo *info, GladeWidget *widget) +glade_widget_fill_from_widget_info (GladeWidgetInfo *info, + GladeWidget *widget, + gboolean apply_props) { guint i; @@ -1768,7 +1892,8 @@ glade_widget_fill_from_widget_info (GladeWidgetInfo *info, GladeWidget *widget) /* Children */ for (i = 0; i < info->n_children; ++i) { - if (!glade_widget_new_child_from_child_info (info->children + i, widget->project, widget)) + if (!glade_widget_new_child_from_child_info (info->children + i, + widget->project, widget)) { g_warning ("Failed to read child of %s", glade_widget_get_name (widget)); @@ -1791,68 +1916,139 @@ glade_widget_fill_from_widget_info (GladeWidgetInfo *info, GladeWidget *widget) } /* Properties */ - for (i = 0; i < info->n_properties; ++i) + if (apply_props) { - if (!glade_widget_apply_property_from_prop_info (info->properties + i, widget, FALSE)) + for (i = 0; i < info->n_properties; ++i) { - g_warning ("Failed to apply property"); - continue; + if (!glade_widget_apply_property_from_prop_info (info->properties + i, + widget)) + { + g_warning ("Failed to apply property"); + continue; + } } } - glade_widget_sync_custom_props (widget); } -static GladeWidget * -glade_widget_new_from_widget_info (GladeWidgetInfo *info, - GladeProject *project, - GladeWidget *parent) +static GValue * +glade_widget_get_property_from_widget_info (GladeWidgetClass *class, + GladeWidgetInfo *info, + const gchar *name) { - GladeWidgetClass *klass; - GladeWidget *widget; - GObject *widget_gtk; - gchar *widget_name; - GArray *params; - GObjectClass *oclass; - GParamSpec **pspec; - GladePropertyClass *glade_property_class; - guint n_props, i; + GValue *value = NULL; + gint i; + gchar *id; - g_return_val_if_fail (info != NULL, NULL); - g_return_val_if_fail (project != NULL, NULL); + for (i = 0; i < info->n_properties; ++i) + { + GladePropInfo *pinfo = info->properties + i; - klass = glade_widget_class_get_by_name (info->classname); - if (!klass) + id = g_strdup (pinfo->name); + glade_util_replace (id, '_', '-'); + + if (!strcmp (id, name)) + { + g_free (id); + return glade_widget_value_from_prop_info (pinfo, class); + } + g_free (id); + } + return value; +} + +static void +glade_widget_params_free (GArray *params) +{ + gint i; + for (i = 0; i < params->len; i++) { - g_warning ("Widget class %s unknown.", info->classname); - return NULL; + GParameter parameter = g_array_index (params, GParameter, i); + g_value_unset (¶meter.value); } + g_array_free (params, TRUE); +} + +static GList * +glade_widget_properties_from_widget_info (GladeWidgetClass *class, + GladeWidgetInfo *info) +{ + GList *properties = NULL, *list; + + for (list = class->properties; list && list->data; list = list->next) + { + GladePropertyClass *pclass = list->data; + GValue *value; + GladeProperty *property; - oclass = g_type_class_ref (klass->type); + /* If there is a value in the XML, initialize property with it, + * otherwise initialize property to default. + */ + value = glade_widget_get_property_from_widget_info + (class, info, pclass->id); + property = glade_property_new (pclass, NULL, value); + properties = g_list_prepend (properties, property); + } + return g_list_reverse (properties); +} + +static GArray * +glade_widget_params_from_widget_info (GladeWidgetClass *widget_class, + GladeWidgetInfo *info) +{ + GladePropertyClass *glade_property_class; + GObjectClass *oclass; + GParamSpec **pspec; + GArray *params; + gint i, n_props; + + oclass = g_type_class_ref (widget_class->type); pspec = g_object_class_list_properties (oclass, &n_props); params = g_array_new (FALSE, FALSE, sizeof (GParameter)); /* preprae parameters that have glade_property_class->def */ for (i = 0; i < n_props; i++) { - GParameter parameter = { 0, }; - - glade_property_class = - glade_widget_class_get_property_class (klass, - pspec[i]->name); - if (!glade_property_class || !glade_property_class->def) + GParameter parameter = { 0, }; + GValue *value; + + if ((glade_property_class = + glade_widget_class_get_property_class (widget_class, + pspec[i]->name)) == NULL) continue; parameter.name = pspec[i]->name; g_value_init (¶meter.value, pspec[i]->value_type); - if (g_value_type_compatible (G_VALUE_TYPE (glade_property_class->def), - G_VALUE_TYPE (¶meter.value))) - g_value_copy (glade_property_class->def, - ¶meter.value); + /* Try filling parameter with value from widget info. + */ + if ((value = glade_widget_get_property_from_widget_info + (widget_class, info, parameter.name)) != NULL) + { + if (g_value_type_compatible (G_VALUE_TYPE (value), + G_VALUE_TYPE (¶meter.value))) + { + g_value_copy (value, ¶meter.value); + g_value_unset (value); + g_free (value); + } + else + { + g_critical ("Type mismatch on %s property of %s", + parameter.name, widget_class->name); + g_value_unset (value); + g_free (value); + continue; + } + } + /* Now try filling the parameter with the default on the GladeWidgetClass. + */ + else if (g_value_type_compatible (G_VALUE_TYPE (glade_property_class->def), + G_VALUE_TYPE (¶meter.value))) + g_value_copy (glade_property_class->def, ¶meter.value); else { g_critical ("Type mismatch on %s property of %s", - parameter.name, klass->name); + parameter.name, widget_class->name); continue; } @@ -1860,23 +2056,49 @@ glade_widget_new_from_widget_info (GladeWidgetInfo *info, } g_free(pspec); - widget_gtk = g_object_newv (klass->type, params->len, - (GParameter *)params->data); + g_type_class_unref (oclass); + + return params; +} + +static GladeWidget * +glade_widget_new_from_widget_info (GladeWidgetInfo *info, + GladeProject *project, + GladeWidget *parent) +{ + GladeWidgetClass *klass; + GladeWidget *widget; + GObject *object; + gchar *widget_name; + GArray *params; + GList *properties; - for (i = 0; i < params->len; i++) + g_return_val_if_fail (info != NULL, NULL); + g_return_val_if_fail (project != NULL, NULL); + + klass = glade_widget_class_get_by_name (info->classname); + if (!klass) { - GParameter parameter = g_array_index (params, GParameter, i); - g_value_unset (¶meter.value); + g_warning ("Widget class %s unknown.", info->classname); + return NULL; } - g_array_free (params, TRUE); - if (klass->pre_create_function) - klass->pre_create_function (widget_gtk); + params = glade_widget_params_from_widget_info (klass, info); + properties = glade_widget_properties_from_widget_info (klass, info); + + object = g_object_newv (klass->type, params->len, + (GParameter *)params->data); + + glade_widget_params_free (params); + widget_name = glade_project_new_widget_name (project, klass->generic_name); - widget = g_object_new (GLADE_TYPE_WIDGET, "class", klass, "project", project, + widget = g_object_new (GLADE_TYPE_WIDGET, + "properties", properties, + "class", klass, + "project", project, "name", widget_name, - "widget", widget_gtk, NULL); + "object", object, NULL); g_free (widget_name); /* create the packing_properties list, without setting them */ @@ -1884,9 +2106,14 @@ glade_widget_new_from_widget_info (GladeWidgetInfo *info, widget->packing_properties = glade_widget_create_packing_properties (parent, widget); - glade_widget_fill_from_widget_info (info, widget); + glade_widget_fill_from_widget_info (info, widget, FALSE); - gtk_widget_show_all (widget->widget); + glade_widget_sync_custom_props (widget); + + glade_widget_class_container_fill_empty (klass, object); + + if (GTK_IS_WIDGET (object)) + gtk_widget_show_all (GTK_WIDGET (object)); return widget; } @@ -1894,7 +2121,7 @@ glade_widget_new_from_widget_info (GladeWidgetInfo *info, /** * When looking for an internal child we have to walk up the hierarchy... */ -static GtkWidget * +static GObject * glade_widget_get_internal_child (GladeWidget *parent, const gchar *internal) { @@ -1902,14 +2129,14 @@ glade_widget_get_internal_child (GladeWidget *parent, { if (parent->widget_class->get_internal_child) { - GtkWidget *widget_gtk; - parent->widget_class->get_internal_child (parent->widget, - internal, &widget_gtk); - return widget_gtk; + GObject *object; + parent->widget_class->get_internal_child (parent->object, + internal, + &object); + return object; } parent = glade_widget_get_parent (parent); } - return NULL; } @@ -1918,8 +2145,8 @@ glade_widget_new_child_from_child_info (GladeChildInfo *info, GladeProject *project, GladeWidget *parent) { - GladeWidget *child; - guint i; + GladeWidget *child; + guint i; g_return_val_if_fail (info != NULL, FALSE); g_return_val_if_fail (project != NULL, FALSE); @@ -1927,53 +2154,48 @@ glade_widget_new_child_from_child_info (GladeChildInfo *info, /* is it a placeholder? */ if (!info->child) { - /* gtk_container_add (GTK_CONTAINER (parent->widget), glade_placeholder_new ()); */ - + /* gtk_container_add (GTK_CONTAINER (parent->widget), + glade_placeholder_new ()); */ return TRUE; } /* is it an internal child? */ if (info->internal_child) { - GtkWidget *child_gtk = glade_widget_get_internal_child (parent, info->internal_child); + GObject *child_object = + glade_widget_get_internal_child (parent, info->internal_child); GladeWidgetClass *child_class; - if (!child_gtk) - { + if (!child_object) + { g_warning ("Failed to locate internal child %s of %s", info->internal_child, glade_widget_get_name (parent)); return FALSE; } - child_class = glade_widget_class_get_by_name (G_OBJECT_TYPE_NAME (child_gtk)); - child = glade_widget_new_for_internal_child (child_class, parent, - child_gtk, info->internal_child); - glade_widget_fill_from_widget_info (info->child, child); + child_class = glade_widget_class_get_by_name (G_OBJECT_TYPE_NAME (child_object)); + child = glade_widget_new_for_internal_child (child_class, + parent, + child_object, + info->internal_child); + + glade_widget_fill_from_widget_info (info->child, child, TRUE); + glade_widget_sync_custom_props (child); } - else - { + else + { child = glade_widget_new_from_widget_info (info->child, project, parent); if (!child) return FALSE; - /* REMOVE ME: fill_empty () is called just after setting - gtkwidget of GladeWidget, remove this if the behaviour - is corrected. */ - if (GTK_IS_BIN (parent->widget)) - { - GtkWidget *child; - - child = gtk_bin_get_child ((GtkBin *) parent->widget); - if (GLADE_IS_PLACEHOLDER (child)) - gtk_container_remove ((GtkContainer *) parent->widget, child); - } - - gtk_container_add (GTK_CONTAINER (parent->widget), child->widget); + child->parent = parent; + glade_widget_class_container_add (parent->widget_class, + parent->object, child->object); } /* Get the packing properties */ for (i = 0; i < info->n_properties; ++i) { - if (!glade_widget_apply_property_from_prop_info (info->properties + i, child, TRUE)) + if (!glade_widget_apply_property_from_prop_info (info->properties + i, child)) { g_warning ("Failed to apply packing property"); continue; diff --git a/src/glade-widget.h b/src/glade-widget.h index 74bf480b..06688665 100644 --- a/src/glade-widget.h +++ b/src/glade-widget.h @@ -19,11 +19,13 @@ typedef struct _GladeWidgetKlass GladeWidgetKlass; struct _GladeWidget { - GObject object; + GObject parent_instance; GladeWidgetClass *widget_class; GladeProject *project; /* A pointer to the project that this widget belongs to. */ + GladeWidget *parent; /* A pointer to the parent widget in the heirarchy */ + char *name; /* The name of the widget. For example window1 or * button2. This is a unique name and is the one * used when loading widget with libglade @@ -35,12 +37,12 @@ struct _GladeWidget * Internal children cannot be deleted. */ - GtkWidget *widget; /* A pointer to the widget that was created. - * and is shown as a "view" of the GladeWidget. - * This widget is updated as the properties are - * modified for the GladeWidget. - */ - + GObject *object; /* A pointer to the object that was created. + * if it is a GtkWidget; it is shown as a "view" + * of the GladeWidget. This object is updated as + * the properties are modified for the GladeWidget. + */ + GList *properties; /* A list of GladeProperty. A GladeProperty is an * instance of a GladePropertyClass. If a * GladePropertyClass for a gtkbutton is label, its @@ -78,40 +80,61 @@ struct _GladeWidgetKlass GladeSignal *new_signal_handler); }; -GType glade_widget_get_type (void); -GladeWidget * glade_widget_new (GladeWidgetClass *klass, GladeProject *project); -GladeWidget * glade_widget_new_for_internal_child (GladeWidgetClass *klass, GladeWidget *parent, GtkWidget *internal_widget, const char *internal_name); - -void glade_widget_set_name (GladeWidget *widget, const char *name); -void glade_widget_set_internal (GladeWidget *widget, const char *internal); -void glade_widget_set_widget (GladeWidget *widget, GtkWidget *widget_gtk); -void glade_widget_set_project (GladeWidget *widget, GladeProject *project); - -const char * glade_widget_get_name (GladeWidget *widget); -const char * glade_widget_get_internal (GladeWidget *widget); -GladeWidgetClass * glade_widget_get_class (GladeWidget *widget); -GladeProject * glade_widget_get_project (GladeWidget *widget); -GtkWidget * glade_widget_get_widget (GladeWidget *widget); -GladeProperty * glade_widget_get_property (GladeWidget *widget, const char *id_property); - -void glade_widget_replace (GtkWidget *old_widget, GtkWidget *new_widget); +GType glade_widget_get_type (void); +GladeWidget * glade_widget_new (GladeWidgetClass *klass, + GladeProject *project); +GladeWidget * glade_widget_new_for_internal_child (GladeWidgetClass *klass, + GladeWidget *parent, + GObject *internal_object, + const char *internal_name); + +void glade_widget_set_name (GladeWidget *widget, + const char *name); +void glade_widget_set_internal (GladeWidget *widget, + const char *internal); +void glade_widget_set_object (GladeWidget *widget, + GObject *new_object); +void glade_widget_set_project (GladeWidget *widget, + GladeProject *project); + +const gchar *glade_widget_get_name (GladeWidget *widget); +const gchar *glade_widget_get_internal (GladeWidget *widget); +GladeWidgetClass *glade_widget_get_class (GladeWidget *widget); +GladeProject *glade_widget_get_project (GladeWidget *widget); +GObject *glade_widget_get_object (GladeWidget *widget); +GladeProperty *glade_widget_get_property (GladeWidget *widget, + const char *id_property); + +void glade_widget_replace (GladeWidget *parent, + GObject *old_object, + GObject *new_object); + +void glade_widget_rebuild (GladeWidget *widget); +GladeWidget *glade_widget_dup (GladeWidget *widget); /* widget signals */ -void glade_widget_add_signal_handler (GladeWidget *widget, GladeSignal *signal_handler); -void glade_widget_remove_signal_handler (GladeWidget *widget, GladeSignal *signal_handler); -void glade_widget_change_signal_handler (GladeWidget *widget, GladeSignal *old_signal_handler, GladeSignal *new_signal_handler); -GPtrArray * glade_widget_list_signal_handlers (GladeWidget *widget, const char *signal_name); /* array of GladeSignal* */ - +void glade_widget_add_signal_handler (GladeWidget *widget, + GladeSignal *signal_handler); +void glade_widget_remove_signal_handler (GladeWidget *widget, + GladeSignal *signal_handler); +void glade_widget_change_signal_handler (GladeWidget *widget, + GladeSignal *old_signal_handler, + GladeSignal *new_signal_handler); +/* array of GladeSignal* */ +GPtrArray * glade_widget_list_signal_handlers (GladeWidget *widget, + const char *signal_name); /* serialization */ -GladeWidgetInfo * glade_widget_write (GladeWidget *widget, GladeInterface *interface); -GladeWidget * glade_widget_read (GladeProject *project, GladeWidgetInfo *info); +GladeWidgetInfo *glade_widget_write (GladeWidget *widget, + GladeInterface *interface); +GladeWidget *glade_widget_read (GladeProject *project, + GladeWidgetInfo *info); /* helper functions */ -#define glade_widget_get_from_gtk_widget(w) g_object_get_data (G_OBJECT (w), "GladeWidgetDataTag") -GladeWidget * glade_widget_get_parent (GladeWidget *widget); +#define glade_widget_get_from_gobject(w) \ + g_object_get_data (G_OBJECT (w), "GladeWidgetDataTag") + +GladeWidget *glade_widget_get_parent (GladeWidget *widget); -void glade_widget_rebuild (GladeWidget *widget); -GladeWidget * glade_widget_dup (GladeWidget *widget); G_END_DECLS diff --git a/src/glade.h b/src/glade.h index 3a9a3573..e7ab35ce 100644 --- a/src/glade.h +++ b/src/glade.h @@ -52,6 +52,8 @@ #define GLADE_TAG_ICON "Icon" #define GLADE_TAG_PROPERTIES "Properties" #define GLADE_TAG_CHILD_PROPERTIES "ChildProperties" +#define GLADE_TAG_CHILD "Child" +#define GLADE_TAG_CHILDREN "Children" #define GLADE_TAG_CONTAINER "Container" #define GLADE_TAG_PROPERTY "Property" #define GLADE_TAG_COMMON "Common" @@ -91,11 +93,17 @@ #define GLADE_TAG_SIGNAL_NAME "SignalName" #define GLADE_TAG_DEFAULT "Default" #define GLADE_TAG_DISABLED "Disabled" -#define GLADE_TAG_REPLACE_CHILD_FUNCTION "ReplaceChildFunction" -#define GLADE_TAG_POST_CREATE_FUNCTION "PostCreateFunction" -#define GLADE_TAG_PRE_CREATE_FUNCTION "PreCreateFunction" -#define GLADE_TAG_FILL_EMPTY_FUNCTION "FillEmptyFunction" +#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_ADD_CHILD_FUNCTION "AddChildFunction" +#define GLADE_TAG_REMOVE_CHILD_FUNCTION "RemoveChildFunction" +#define GLADE_TAG_GET_CHILDREN_FUNCTION "GetChildrenFunction" +#define GLADE_TAG_GET_ALL_CHILDREN_FUNCTION "GetAllChildrenFunction" +#define GLADE_TAG_CHILD_SET_PROP_FUNCTION "ChildSetPropertyFunction" +#define GLADE_TAG_CHILD_GET_PROP_FUNCTION "ChildGetPropertyFunction" + #define GLADE_TAG_IN_PALETTE "InPalette" #define GLADE_TAG_CATALOG "GladeCatalog" diff --git a/widgets/Makefile.am b/widgets/Makefile.am index 7f7e932f..0e44596a 100644 --- a/widgets/Makefile.am +++ b/widgets/Makefile.am @@ -9,7 +9,6 @@ widgets_DATA = \ gtkaccellabel.xml \ gtkbox.xml \ gtkbutton.xml \ - gtkbuttonbox.xml \ gtkcheckbutton.xml \ gtkcontainer.xml \ gtkdialog.xml \ diff --git a/widgets/gtk-additional.xml b/widgets/gtk-additional.xml index c4ab9705..7d65b385 100644 --- a/widgets/gtk-additional.xml +++ b/widgets/gtk-additional.xml @@ -10,7 +10,6 @@ <GladeWidget name="GtkHScrollbar" generic_name="hscrollbar" palette_name="Horizontal Scrollbar"/> <GladeWidget name="GtkVScrollbar" generic_name="vscrollbar" palette_name="Vertical Scrollbar"/> - <GladeWidget name="GtkButtonBox" filename="gtkbuttonbox.xml"/> <GladeWidget name="GtkHButtonBox" generic_name="hbuttonbox" palette_name="Horizontal Button Box"/> <GladeWidget name="GtkVButtonBox" generic_name="vbuttonbox" palette_name="Vertical Button Box"/> diff --git a/widgets/gtkbox.xml b/widgets/gtkbox.xml index 7c7dc3f8..5b8af969 100644 --- a/widgets/gtkbox.xml +++ b/widgets/gtkbox.xml @@ -1,7 +1,5 @@ <GladeWidgetClass> - <FillEmptyFunction>empty</FillEmptyFunction> - <Properties> <Property Id="size" Name="Number of items" Query="TRUE" Default="3"> @@ -21,4 +19,11 @@ </Properties> + <Children> + <Child> + <Type>GtkWidget</Type> + <FillEmptyFunction>empty</FillEmptyFunction> + </Child> + </Children> + </GladeWidgetClass> diff --git a/widgets/gtkbutton.xml b/widgets/gtkbutton.xml index e4a4169d..363b5639 100644 --- a/widgets/gtkbutton.xml +++ b/widgets/gtkbutton.xml @@ -1,7 +1,5 @@ <GladeWidgetClass> - <FillEmptyFunction>ignore</FillEmptyFunction> - <Properties> <Property Id="stock" Name="Stock Button" Default="glade-none"> @@ -16,8 +14,15 @@ <GetFunction>ignore</GetFunction> </Property> - <Property Id="label" Default="button"/> + <Property Id="label" Default="button"/> </Properties> + + <Children> + <Child> + <Type>GtkWidget</Type> + <FillEmptyFunction>empty</FillEmptyFunction> + </Child> + </Children> </GladeWidgetClass> diff --git a/widgets/gtkcontainer.xml b/widgets/gtkcontainer.xml index 5988f728..b1eb42ec 100644 --- a/widgets/gtkcontainer.xml +++ b/widgets/gtkcontainer.xml @@ -1,6 +1,11 @@ <GladeWidgetClass> - <ReplaceChildFunction>glade_gtk_container_replace_child</ReplaceChildFunction> - <FillEmptyFunction>glade_gtk_container_fill_empty</FillEmptyFunction> + <Children> + <Child> + <Type>GtkWidget</Type> + <ReplaceChildFunction>glade_gtk_container_replace_child</ReplaceChildFunction> + <FillEmptyFunction>glade_gtk_container_fill_empty</FillEmptyFunction> + </Child> + </Children> </GladeWidgetClass> diff --git a/widgets/gtkdialog.xml b/widgets/gtkdialog.xml index 33ed6fcd..d550c4a2 100644 --- a/widgets/gtkdialog.xml +++ b/widgets/gtkdialog.xml @@ -1,7 +1,6 @@ <GladeWidgetClass> <PostCreateFunction>glade_gtk_dialog_post_create</PostCreateFunction> - <FillEmptyFunction>glade_gtk_dialog_fill_empty</FillEmptyFunction> <GetInternalChildFunction>glade_gtk_dialog_get_internal_child</GetInternalChildFunction> <ChildPropertyApplies>glade_gtk_dialog_child_property_applies</ChildPropertyApplies> @@ -13,17 +12,25 @@ <Property Id="default-height" Default="0" Optional="True" OptionalDefault="False"/> </Properties> + + <Children> + <Child> + <Type>GtkWidget</Type> + <FillEmptyFunction>glade_gtk_dialog_fill_empty</FillEmptyFunction> + <!-- That's supported, and IMO is the right way to handle response-id (and it works), but it's not backwards compatible with response-id being a property as in glade-2. So by now we will just add a fake response-id property to buttons - <ChildProperties> - <Property Id="response-id" Name="Response ID" Default="0" Common="False"> - <Spec>glade_gtk_standard_int_spec</Spec> - <Tooltip>The response ID of this button in the dialog</Tooltip> - <SetFunction>ignore</SetFunction> - <GetFunction>ignore</GetFunction> - </Property> - </ChildProperties> + <Properties> + <Property Id="response-id" Name="Response ID" Default="0" Common="False"> + <Spec>glade_gtk_standard_int_spec</Spec> + <Tooltip>The response ID of this button in the dialog</Tooltip> + <SetFunction>ignore</SetFunction> + <GetFunction>ignore</GetFunction> + </Property> + </Properties> --> + </Child> + </Children> </GladeWidgetClass> diff --git a/widgets/gtkfixed.xml b/widgets/gtkfixed.xml index 6996769b..1fdf08db 100644 --- a/widgets/gtkfixed.xml +++ b/widgets/gtkfixed.xml @@ -1,5 +1,11 @@ <GladeWidgetClass> <PostCreateFunction>glade_gtk_fixed_post_create</PostCreateFunction> - <FillEmptyFunction>empty</FillEmptyFunction> + + <Children> + <Child> + <Type>GtkWidget</Type> + <FillEmptyFunction>empty</FillEmptyFunction> + </Child> + </Children> </GladeWidgetClass> diff --git a/widgets/gtkmenubar.xml b/widgets/gtkmenubar.xml index 1038dc52..8165b009 100644 --- a/widgets/gtkmenubar.xml +++ b/widgets/gtkmenubar.xml @@ -1,6 +1,11 @@ <GladeWidgetClass> <!-- menubar is a container you can't add placeholders to it --> - <FillEmptyFunction>ignore</FillEmptyFunction> + <Children> + <Child> + <Type>GtkWidget</Type> + <FillEmptyFunction>empty</FillEmptyFunction> + </Child> + </Children> </GladeWidgetClass> diff --git a/widgets/gtknotebook.xml b/widgets/gtknotebook.xml index 0f295942..a4c3214b 100644 --- a/widgets/gtknotebook.xml +++ b/widgets/gtknotebook.xml @@ -1,9 +1,5 @@ <GladeWidgetClass> - <FillEmptyFunction>empty</FillEmptyFunction> - - <ReplaceChildFunction>glade_gtk_notebook_replace_child</ReplaceChildFunction> - <Properties> <Property Id="pages" Name="Number of pages" Default="3" Query="TRUE"> @@ -23,13 +19,20 @@ </Properties> - <ChildProperties> - <Property Id="tab-label" Name="Tab Label Text" > - <Spec>glade_gtk_standard_string_spec</Spec> - <Tooltip>The tab label text of this page widget</Tooltip> - <SetFunction>glade_gtk_notebook_set_tab_label_text</SetFunction> - <GetFunction>glade_gtk_notebook_get_tab_label_text</GetFunction> - </Property> - </ChildProperties> + <Children> + <Child> + <Type>GtkWidget</Type> + <FillEmptyFunction>empty</FillEmptyFunction> + <ReplaceChildFunction>glade_gtk_notebook_replace_child</ReplaceChildFunction> + <Properties> + <Property Id="tab-label" Name="Tab Label Text" > + <Spec>glade_gtk_standard_string_spec</Spec> + <Tooltip>The tab label text of this page widget</Tooltip> + <SetFunction>glade_gtk_notebook_set_tab_label_text</SetFunction> + <GetFunction>glade_gtk_notebook_get_tab_label_text</GetFunction> + </Property> + </Properties> + </Child> + </Children> </GladeWidgetClass> diff --git a/widgets/gtkpaned.xml b/widgets/gtkpaned.xml index 7f2b3082..8f7c5e1d 100644 --- a/widgets/gtkpaned.xml +++ b/widgets/gtkpaned.xml @@ -1,5 +1,10 @@ <GladeWidgetClass> - <FillEmptyFunction>glade_gtk_paned_fill_empty</FillEmptyFunction> + <Children> + <Child> + <Type>GtkWidget</Type> + <FillEmptyFunction>glade_gtk_paned_fill_empty</FillEmptyFunction> + </Child> + </Children> </GladeWidgetClass> diff --git a/widgets/gtkprogressbar.xml b/widgets/gtkprogressbar.xml index 92f34c4d..238c3277 100644 --- a/widgets/gtkprogressbar.xml +++ b/widgets/gtkprogressbar.xml @@ -18,13 +18,13 @@ <Property Id="text"/> <Property Id="text-xalign"> <Parameters> - <Parameter Key="StepIncrement" Value="0.05"/> - </Parameters> + <Parameter Key="StepIncrement" Value="0.05"/> + </Parameters> </Property> <Property Id="text-yalign"> <Parameters> - <Parameter Key="StepIncrement" Value="0.05"/> - </Parameters> + <Parameter Key="StepIncrement" Value="0.05"/> + </Parameters> </Property> </Properties> diff --git a/widgets/gtkspinbutton.xml b/widgets/gtkspinbutton.xml index a5df2993..877be9b0 100644 --- a/widgets/gtkspinbutton.xml +++ b/widgets/gtkspinbutton.xml @@ -23,17 +23,6 @@ <SetFunction>glade_gtk_spin_button_set_step_increment</SetFunction> </Property> - <!-- - <Parameters> - <Parameter Key="Default" Value="1"/> - <Parameter Key="Min" Value="0"/> - <Parameter Key="Max" Value="100"/> - <Parameter Key="StepIncrement" Value="1"/> - <Parameter Key="PageIncrement" Value="10"/> - <Parameter Key="PageSize" Value="10"/> - </Parameters> - --> - </Properties> </GladeWidgetClass> diff --git a/widgets/gtkstatusbar.xml b/widgets/gtkstatusbar.xml index f8b94202..55da7746 100644 --- a/widgets/gtkstatusbar.xml +++ b/widgets/gtkstatusbar.xml @@ -1,7 +1,5 @@ <GladeWidgetClass> - <FillEmptyFunction>ignore</FillEmptyFunction> - <Properties> <Property Id="size" Disabled="TRUE" /> @@ -14,6 +12,13 @@ </Properties> + <Children> + <Child> + <Type>GtkWidget</Type> + <FillEmptyFunction>empty</FillEmptyFunction> + </Child> + </Children> + </GladeWidgetClass> diff --git a/widgets/gtktable.xml b/widgets/gtktable.xml index 6b982543..7a31ab17 100644 --- a/widgets/gtktable.xml +++ b/widgets/gtktable.xml @@ -1,7 +1,5 @@ <GladeWidgetClass> - <FillEmptyFunction>empty</FillEmptyFunction> - <Properties> <Property Id="n-rows" Default="3" Query="TRUE"> @@ -30,4 +28,11 @@ </Properties> + <Children> + <Child> + <Type>GtkWidget</Type> + <FillEmptyFunction>empty</FillEmptyFunction> + </Child> + </Children> + </GladeWidgetClass> diff --git a/widgets/gtktoolbar.xml b/widgets/gtktoolbar.xml index 2679c315..29495654 100644 --- a/widgets/gtktoolbar.xml +++ b/widgets/gtktoolbar.xml @@ -1,7 +1,5 @@ <GladeWidgetClass> - <FillEmptyFunction>empty</FillEmptyFunction> - <Properties> <Property Id="size" Name="Size" Default="3" Query="TRUE"> @@ -21,4 +19,11 @@ </Properties> + <Children> + <Child> + <Type>GtkWidget</Type> + <FillEmptyFunction>empty</FillEmptyFunction> + </Child> + </Children> + </GladeWidgetClass> diff --git a/widgets/gtktreeview.xml b/widgets/gtktreeview.xml index 9b6dedbc..1baa1a20 100644 --- a/widgets/gtktreeview.xml +++ b/widgets/gtktreeview.xml @@ -1,5 +1,5 @@ <GladeWidgetClass> - <PreCreateFunction>glade_gtk_tree_view_pre_create</PreCreateFunction> + <PostCreateFunction>glade_gtk_tree_view_post_create</PostCreateFunction> </GladeWidgetClass> diff --git a/widgets/gtkwidget.xml b/widgets/gtkwidget.xml index 54f4ef7c..bd231cfb 100644 --- a/widgets/gtkwidget.xml +++ b/widgets/gtkwidget.xml @@ -6,9 +6,9 @@ <GetFunction>ignore</GetFunction> </Property> - <Property Common="True" Optional="True" OptionalDefault="False" Default="0" Id="width-request"/> + <Property Common="True" Optional="True" OptionalDefault="False" Default="0" Id="width-request"/> - <Property Common="True" Optional="True" OptionalDefault="False" Default="0" Id="height-request"/> + <Property Common="True" Optional="True" OptionalDefault="False" Default="0" Id="height-request"/> <Property Common="True" Id="tooltip" Name="Tooltip" Visible="glade_gtk_widget_condition" Default=""> <Spec>glade_gtk_standard_string_spec</Spec> |