diff options
-rw-r--r-- | ChangeLog | 69 | ||||
-rw-r--r-- | src/glade-catalog.c | 5 | ||||
-rw-r--r-- | src/glade-clipboard.c | 2 | ||||
-rw-r--r-- | src/glade-command.c | 254 | ||||
-rw-r--r-- | src/glade-command.h | 9 | ||||
-rw-r--r-- | src/glade-editor.c | 155 | ||||
-rw-r--r-- | src/glade-editor.h | 8 | ||||
-rw-r--r-- | src/glade-gtk.c | 30 | ||||
-rw-r--r-- | src/glade-placeholder.c | 2 | ||||
-rw-r--r-- | src/glade-popup.c | 95 | ||||
-rw-r--r-- | src/glade-popup.h | 2 | ||||
-rw-r--r-- | src/glade-project-view.c | 183 | ||||
-rw-r--r-- | src/glade-project-window.c | 65 | ||||
-rw-r--r-- | src/glade-project.c | 8 | ||||
-rw-r--r-- | src/glade-property-class.c | 8 | ||||
-rw-r--r-- | src/glade-property.c | 13 | ||||
-rw-r--r-- | src/glade-signal-editor.c | 487 | ||||
-rw-r--r-- | src/glade-signal.c | 49 | ||||
-rw-r--r-- | src/glade-signal.h | 14 | ||||
-rw-r--r-- | src/glade-utils.c | 76 | ||||
-rw-r--r-- | src/glade-utils.h | 27 | ||||
-rw-r--r-- | src/glade-widget-class.c | 78 | ||||
-rw-r--r-- | src/glade-widget-class.h | 2 | ||||
-rw-r--r-- | src/glade-widget.c | 283 | ||||
-rw-r--r-- | src/glade-widget.h | 5 |
25 files changed, 1348 insertions, 581 deletions
@@ -1,3 +1,72 @@ +2004-12-15 Tristan Van Berkom <tvb@cvs.gnome.org> + + * src/glade-catalog.c: pallet_name is no longer "required" in the catalog, + if it is present, then the widget goes in the pallet, if there is a generic + name, it will be used in the case of non-widgets. + + * src/glade-command.c: glade_command_create no longer nescesitates a placeholder + and now has a "parent" argument for the case of (!toplevel && non-widget) + (surrounding code adjusted to work with non-widgets, glade_command_delete + stuff included). + + * src/glade-editor.c: + - Widget page is now called General page + - Name field not appended to non-widgets + - Adjusted text inputs to only set properties on TAB or ENTER + (or focus changes in the case of multi line entries) + This heavily reduces spamming of the property system as properties + dont get synchronized for every single charachter change. + + * src/glade-signal-editor.c: Implemented "object" and "lookup" fields. + + * src/glade-signal.c: Implemented "object" and "lookup" fields. + + * src/glade-gtk.c: GtkFixed code fixed to not needlessly create placeholders + at child create time (go directly to glade_command_create() without passing + go or collecting 200 dollars). + (Also fixed name of enum type glade_gtk_stock_get_type) + + * src/glade-placeholder.c: Use new glade_command_create () + + * src/glade-popup.c: + - Added code needed for addition of non-widgets. + - Added "add_children" arg to glade_popup_widget_pop () + + * src/glade-project-view.c: + - fixed bug 145299. + - Added popup code to treeview. + - Sort widgets in treeview alphabeticly + - Window is now scrollable. + + * src/glade-project-window.c: Fixed some error messages, used new + glade_command_create() + + * src/glade-property.c: Fixed a bug in rebuilding of widgets + (project list needs to be searched to find out if the widget is + actualy in the project). + + * src/glade-property-class.c: Made custom props load tooltips from pspec + blurbs as well as the xml file. + + * src/glade-utils.c: + - glade_utils_draw_nodes_idle(), dont try to draw nodes on non-widgets. + - added glade_util_widget_pastable() + - added glade_util_gtkcontainer_relation() + + * src/glade-widget-class.[ch]: + - added glade_widget_class_get_by_type () + - added glade_widget_class_get_derived_types () + + * src/glade-widget.c: + - added glade_widget_sync_packing_props () + - added glade_widget_set_parent (). + - Made widgets parent a property of widget + - glade_widget_new() now takes a "parent" argument. + - removed glade_widget_update_parent() which was more confusing + than anything else. + - glade_widget_dup() now duplicates widget names as well. + + 2004-11-16 Tristan Van Berkom <tristan.van.berkom@gmail.com> * Replaced `GtkWidget *' with `GObject *' throughout the code diff --git a/src/glade-catalog.c b/src/glade-catalog.c index 28464c8d..bc779bec 100644 --- a/src/glade-catalog.c +++ b/src/glade-catalog.c @@ -124,11 +124,8 @@ glade_catalog_load (const char *base_catalog_filename) /* get the specific library to the widget class, if any */ base_widget_class_library = glade_xml_get_property_string (widget_node, "library"); - generic_name = glade_xml_get_property_string (widget_node, "generic_name"); - palette_name = NULL; - if (generic_name != NULL) - palette_name = glade_xml_get_property_string_required (widget_node, "palette_name", name); + palette_name = glade_xml_get_property_string (widget_node, "palette_name"); base_filename = glade_xml_get_property_string (widget_node, "filename"); diff --git a/src/glade-clipboard.c b/src/glade-clipboard.c index 24273902..e343f354 100644 --- a/src/glade-clipboard.c +++ b/src/glade-clipboard.c @@ -140,3 +140,5 @@ glade_clipboard_remove (GladeClipboard *clipboard, GladeWidget *widget) if (clipboard->view) glade_clipboard_view_remove (GLADE_CLIPBOARD_VIEW (clipboard->view), widget); } + + diff --git a/src/glade-command.c b/src/glade-command.c index 229be361..d3eb1af8 100644 --- a/src/glade-command.c +++ b/src/glade-command.c @@ -456,6 +456,7 @@ glade_command_set_name_execute (GladeCommand *cmd) g_return_val_if_fail (me->name != NULL, TRUE); glade_widget_set_name (me->widget, me->name); + tmp = me->old_name; me->old_name = me->name; me->name = tmp; @@ -547,11 +548,11 @@ glade_command_set_name (GladeWidget *widget, const gchar* name) typedef struct { GladeCommand parent; - GladeWidget *widget; + GladeWidget *parent_widget; + GladeWidget *widget; GladePlaceholder *placeholder; - gboolean create; - - gulong handler_id; + + gboolean create; } GladeCommandCreateDelete; GLADE_MAKE_COMMAND (GladeCommandCreateDelete, glade_command_create_delete); @@ -571,13 +572,23 @@ static gboolean glade_command_create_execute (GladeCommandCreateDelete *me) { GladeWidget *widget = me->widget; + GladeWidget *parent = me->parent_widget; GladePlaceholder *placeholder = me->placeholder; - if (!GTK_WIDGET_TOPLEVEL (widget->object)) - glade_widget_replace - (glade_placeholder_get_parent (placeholder), - G_OBJECT (placeholder), widget->object); - + if (parent) + { + if (placeholder) + glade_widget_replace + (parent, G_OBJECT (placeholder), widget->object); + else + { + glade_widget_class_container_add (parent->widget_class, + parent->object, + widget->object); + glade_widget_set_parent (widget, parent); + } + } + glade_project_add_object (widget->project, widget->object); glade_project_selection_set (widget->project, widget->object, TRUE); @@ -591,22 +602,20 @@ static gboolean glade_command_delete_execute (GladeCommandCreateDelete *me) { GladeWidget *widget = me->widget; - GladeWidget *parent; + GladeWidget *parent = me->parent_widget; g_return_val_if_fail (widget != NULL, TRUE); parent = glade_widget_get_parent (widget); if (parent) { - if (me->placeholder == NULL) - { - me->placeholder = GLADE_PLACEHOLDER (glade_placeholder_new ()); - g_object_ref (G_OBJECT (me->placeholder)); - } - - glade_widget_replace - (glade_widget_get_parent (widget), - widget->object, G_OBJECT (me->placeholder)); + if (me->placeholder) + glade_widget_replace + (parent, widget->object, G_OBJECT (me->placeholder)); + else + glade_widget_class_container_remove (parent->widget_class, + parent->object, + widget->object); } if (GTK_IS_WIDGET (widget->object)) @@ -670,9 +679,10 @@ glade_command_create_delete_collapse (GladeCommand *this, GladeCommand *other) * Placeholder arg may be NULL for toplevel widgets */ static void -glade_command_create_delete_common (GladeWidget *widget, +glade_command_create_delete_common (GladeWidget *widget, + GladeWidget *parent, GladePlaceholder *placeholder, - gboolean create) + gboolean create) { GladeCommandCreateDelete *me; GladeCommand *cmd; @@ -680,10 +690,11 @@ glade_command_create_delete_common (GladeWidget *widget, me = g_object_new (GLADE_COMMAND_CREATE_DELETE_TYPE, NULL); cmd = GLADE_COMMAND (me); - me->widget = g_object_ref(widget); - me->create = create; - me->placeholder = placeholder; - cmd->description = + me->widget = g_object_ref(widget); + me->create = create; + me->placeholder = placeholder; + me->parent_widget = parent; + cmd->description = g_strdup_printf (_("%s %s"), create ? "Create" : "Delete", widget->name); @@ -709,7 +720,8 @@ glade_command_delete (GladeWidget *widget) if (widget->internal) return; - glade_command_create_delete_common (widget, NULL, FALSE); + glade_command_create_delete_common (widget, glade_widget_get_parent (widget), + NULL, FALSE); } /** @@ -728,36 +740,40 @@ glade_command_delete (GladeWidget *widget) */ void glade_command_create (GladeWidgetClass *class, + GladeWidget *parent, GladePlaceholder *placeholder, - GladeProject *project) + GladeProject *project) { - GladeProjectWindow *gpw; - GladeWidget *widget; - GladeWidget *parent = NULL; + GladeProjectWindow *gpw = glade_project_window_get (); + GladeWidget *widget; g_return_if_fail (GLADE_IS_WIDGET_CLASS (class)); - g_return_if_fail (placeholder != NULL || GLADE_IS_PROJECT (project)); - gpw = glade_project_window_get (); + /* Need either a parent or a placeholder or a project + */ + g_return_if_fail (parent != NULL || + placeholder != NULL || + GLADE_IS_PROJECT (project)); + g_assert (gpw != NULL); g_return_if_fail (GLADE_IS_PALETTE (gpw->palette)); - /* AFAIK Only GtkWindow and derivaitves can be toplevels. */ - if (g_type_is_a (class->type, GTK_TYPE_WINDOW) == FALSE) + if (g_type_is_a (class->type, GTK_TYPE_WINDOW) == FALSE && !parent) { - parent = glade_placeholder_get_parent (placeholder); - g_return_if_fail (parent != NULL); + g_return_if_fail (placeholder != NULL); + g_return_if_fail ((parent = glade_placeholder_get_parent (placeholder))); + if (!project) project = parent->project; } + else if (parent) project = parent->project; - if (!project) - project = parent->project; + g_return_if_fail (project != NULL); - widget = glade_widget_new (class, project); + widget = glade_widget_new (parent, class, project); /* widget may be null, e.g. the user clicked cancel on a query */ if (widget == NULL) return; - glade_command_create_delete_common (widget, placeholder, TRUE); + glade_command_create_delete_common (widget, parent, placeholder, TRUE); /* reset the palette */ glade_palette_unselect_widget (gpw->palette); @@ -778,10 +794,10 @@ typedef enum { typedef struct { GladeCommand parent; - GladeClipboard *clipboard; - GladeWidget *widget; - GladePlaceholder *placeholder; - GladeCutCopyPasteType type; + GladeWidget *parent_widget; + GladeWidget *widget; + GladePlaceholder *placeholder; + GladeCutCopyPasteType type; } GladeCommandCutCopyPaste; @@ -795,31 +811,34 @@ GLADE_MAKE_COMMAND (GladeCommandCutCopyPaste, glade_command_cut_copy_paste); static gboolean glade_command_paste_execute (GladeCommandCutCopyPaste *me) { - GladeWidget *glade_widget = me->widget; - GladePlaceholder *placeholder = me->placeholder; - GladeWidget *parent; - GladeProject *project; + GladeProjectWindow *gpw = glade_project_window_get (); - g_return_val_if_fail (g_list_find (me->clipboard->widgets, glade_widget), TRUE); + g_return_val_if_fail (g_list_find (gpw->clipboard->widgets, me->widget), TRUE); - parent = glade_placeholder_get_parent (placeholder); - project = parent->project; - - if (!GTK_WIDGET_TOPLEVEL (glade_widget->object)) + if (me->parent_widget != NULL) { - g_object_ref (G_OBJECT (placeholder)); - glade_widget_replace - (glade_placeholder_get_parent (placeholder), - G_OBJECT (placeholder), glade_widget->object); + if (me->placeholder) + glade_widget_replace + (me->parent_widget, + G_OBJECT (me->placeholder), + me->widget->object); + else + { + glade_widget_class_container_add + (me->parent_widget->widget_class, + me->parent_widget->object, + me->widget->object); + glade_widget_set_parent (me->widget, me->parent_widget); + } } - glade_project_add_object (project, glade_widget->object); - glade_project_selection_set (glade_widget->project, glade_widget->object, TRUE); + glade_project_add_object (me->widget->project, me->widget->object); + glade_project_selection_set (me->widget->project, me->widget->object, TRUE); - if (GTK_IS_WIDGET (glade_widget->object)) - gtk_widget_show_all (GTK_WIDGET (glade_widget->object)); + if (GTK_IS_WIDGET (me->widget->object)) + gtk_widget_show_all (GTK_WIDGET (me->widget->object)); - glade_clipboard_remove (me->clipboard, glade_widget); + glade_clipboard_remove (gpw->clipboard, me->widget); return TRUE; } @@ -827,29 +846,32 @@ glade_command_paste_execute (GladeCommandCutCopyPaste *me) static gboolean glade_command_cut_execute (GladeCommandCutCopyPaste *me) { - GladeWidget *glade_widget = me->widget; + GladeProjectWindow *gpw = glade_project_window_get (); - g_return_val_if_fail (glade_widget != NULL, TRUE); + g_return_val_if_fail (me->widget != NULL, TRUE); - glade_clipboard_add (me->clipboard, glade_widget); + glade_clipboard_add (gpw->clipboard, me->widget); - if (glade_widget_get_parent (glade_widget)) + if (me->parent_widget) { - if (me->placeholder == NULL) - { - me->placeholder = GLADE_PLACEHOLDER (glade_placeholder_new ()); - g_object_ref (G_OBJECT (me->placeholder)); - } - - glade_widget_replace - (glade_widget_get_parent (glade_widget), - glade_widget->object, G_OBJECT (me->placeholder)); + if (me->placeholder) + glade_widget_replace + (me->parent_widget, + me->widget->object, + G_OBJECT (me->placeholder)); + else + glade_widget_class_container_remove + (me->parent_widget->widget_class, + me->parent_widget->object, + me->widget->object); } + + if (GTK_IS_WIDGET (me->widget->object)) + gtk_widget_hide (GTK_WIDGET (me->widget->object)); - if (GTK_IS_WIDGET (glade_widget->object)) - gtk_widget_hide (GTK_WIDGET (glade_widget->object)); - - glade_project_remove_object (glade_widget->project, glade_widget->object); + /* This doesn't NULLify the widget->project pointer. + */ + glade_project_remove_object (me->widget->project, me->widget->object); return TRUE; } @@ -857,14 +879,16 @@ glade_command_cut_execute (GladeCommandCutCopyPaste *me) static gboolean glade_command_copy_execute (GladeCommandCutCopyPaste *me) { - glade_clipboard_add (me->clipboard, me->widget); + GladeProjectWindow *gpw = glade_project_window_get (); + glade_clipboard_add (gpw->clipboard, me->widget); return TRUE; } static gboolean glade_command_copy_undo (GladeCommandCutCopyPaste *me) { - glade_clipboard_remove (me->clipboard, me->widget); + GladeProjectWindow *gpw = glade_project_window_get (); + glade_clipboard_remove (gpw->clipboard, me->widget); return TRUE; } @@ -944,31 +968,33 @@ glade_command_cut_copy_paste_collapse (GladeCommand *this, GladeCommand *other) } static void -glade_command_cut_copy_paste_common (GladeWidget *widget, - GladePlaceholder *placeholder, - GladeProject *project, - GladeCutCopyPasteType type) +glade_command_cut_copy_paste_common (GladeWidget *widget, + GladeWidget *parent, + GladePlaceholder *placeholder, + GladeProject *project, + GladeCutCopyPasteType type, + gboolean needs_placeholder) { GladeCommandCutCopyPaste *me; GladeCommand *cmd; - GladeProjectWindow *gpw; me = (GladeCommandCutCopyPaste *) g_object_new (GLADE_COMMAND_CUT_COPY_PASTE_TYPE, NULL); cmd = (GladeCommand *) me; - - gpw = glade_project_window_get (); - me->type = type; - me->widget = + me->type = type; + me->widget = (type == GLADE_COPY) ? glade_widget_dup (widget) : g_object_ref (widget); - me->placeholder = placeholder; - me->clipboard = gpw->clipboard; + me->parent_widget = parent; - if (me->placeholder) - g_object_ref (G_OBJECT (me->placeholder)); + me->placeholder = + (placeholder != NULL) ? placeholder : + (needs_placeholder ? + (GtkWidget *) glade_placeholder_new () : NULL); + if (me->placeholder) g_object_ref (placeholder); + switch (type) { case GLADE_CUT: cmd->description = g_strdup_printf (_("Cut %s"), widget->name); @@ -997,27 +1023,19 @@ glade_command_cut_copy_paste_common (GladeWidget *widget, * TODO: write me */ void -glade_command_paste (GladePlaceholder *placeholder) +glade_command_paste (GladeWidget *parent, GladePlaceholder *placeholder) { GladeProjectWindow *gpw; GladeWidget *widget; - GladeWidget *parent; gpw = glade_project_window_get (); - if (!placeholder) { - glade_util_ui_warn (gpw->window, _("Placeholder not selected!")); - return; - } - - g_return_if_fail (GLADE_IS_PLACEHOLDER (placeholder)); - widget = gpw->clipboard->curr; if (widget == NULL) return; - parent = glade_placeholder_get_parent (placeholder); - glade_command_cut_copy_paste_common (widget, placeholder, parent->project, GLADE_PASTE); + glade_command_cut_copy_paste_common (widget, parent, placeholder, + parent->project, GLADE_PASTE, FALSE); } /** @@ -1027,24 +1045,17 @@ glade_command_paste (GladePlaceholder *placeholder) * TODO: write me */ void -glade_command_cut (GladeWidget *widget) +glade_command_cut (GladeWidget *widget, gboolean needs_placeholder) { - GladeProjectWindow *gpw; - - gpw = glade_project_window_get (); - - if (!widget) { - glade_util_ui_warn (gpw->window, _("No widget selected!")); - return; - } - g_return_if_fail (GLADE_IS_WIDGET (widget)); /* internal children cannot be cut. Should we notify the user? */ if (widget->internal) return; - glade_command_cut_copy_paste_common (widget, NULL, widget->project, GLADE_CUT); + glade_command_cut_copy_paste_common (widget, glade_widget_get_parent (widget), + NULL, widget->project, GLADE_CUT, + needs_placeholder); } /** @@ -1056,14 +1067,6 @@ glade_command_cut (GladeWidget *widget) void glade_command_copy (GladeWidget *widget) { - GladeProjectWindow *gpw; - - gpw = glade_project_window_get (); - - if (!widget) { - glade_util_ui_warn (gpw->window, _("No widget selected!")); - return; - } g_return_if_fail (GLADE_IS_WIDGET (widget)); @@ -1071,7 +1074,8 @@ glade_command_copy (GladeWidget *widget) if (widget->internal) return; - glade_command_cut_copy_paste_common (widget, NULL, widget->project, GLADE_COPY); + glade_command_cut_copy_paste_common (widget, glade_widget_get_parent (widget), + NULL, widget->project, GLADE_COPY, FALSE); } /*********************************************************/ diff --git a/src/glade-command.h b/src/glade-command.h index a5d73063..b76f3963 100644 --- a/src/glade-command.h +++ b/src/glade-command.h @@ -48,11 +48,14 @@ void glade_command_set_property (GladeProperty *property, const GValue *value); void glade_command_set_name (GladeWidget *glade_widget, const gchar *name); void glade_command_delete (GladeWidget *glade_widget); -void glade_command_create (GladeWidgetClass *widget_class, GladePlaceholder *placeholder, GladeProject *project); +void glade_command_create (GladeWidgetClass *widget_class, + GladeWidget *parent, + GladePlaceholder *placeholder, + GladeProject *project); -void glade_command_cut (GladeWidget *glade_widget); +void glade_command_cut (GladeWidget *widget, gboolean needs_placeholder); void glade_command_copy (GladeWidget *glade_widget); -void glade_command_paste (GladePlaceholder *placeholder); +void glade_command_paste (GladeWidget *parent, GladePlaceholder *placeholder); void glade_command_add_signal (GladeWidget *glade_widget, const GladeSignal *signal); void glade_command_remove_signal (GladeWidget *glade_widget, const GladeSignal *signal); diff --git a/src/glade-editor.c b/src/glade-editor.c index 063b9d90..6e754212 100644 --- a/src/glade-editor.c +++ b/src/glade-editor.c @@ -159,14 +159,16 @@ glade_editor_notebook_page (const gchar *name, GtkWidget *notebook) static void glade_editor_init (GladeEditor *editor) { - editor->tooltips = gtk_tooltips_new (); - - editor->vbox_widget = glade_editor_notebook_page (_("Widget"), GTK_WIDGET (editor)); + editor->vbox_widget = glade_editor_notebook_page (_("General"), GTK_WIDGET (editor)); editor->vbox_packing = glade_editor_notebook_page (_("Packing"), GTK_WIDGET (editor)); editor->vbox_common = glade_editor_notebook_page (_("Common"), GTK_WIDGET (editor)); editor->vbox_signals = glade_editor_notebook_page (_("Signals"), GTK_WIDGET (editor)); editor->widget_tables = NULL; editor->loading = FALSE; + + /* Common page is removed for non-widgets. + */ + g_object_ref (G_OBJECT (editor->vbox_common)); } /** @@ -203,8 +205,6 @@ glade_editor_widget_name_changed (GtkWidget *editable, GladeEditor *editor) if (editor->loading) return; - 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); glade_command_set_name (widget, new_name); @@ -227,7 +227,7 @@ glade_editor_property_changed_text_common (GladeProperty *property, } static void -glade_editor_property_changed_text (GtkWidget *entry, +glade_editor_property_changed_text (GtkWidget *entry, GladeEditorProperty *property) { gchar *text; @@ -238,38 +238,47 @@ glade_editor_property_changed_text (GtkWidget *entry, return; text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); - glade_editor_property_changed_text_common (property->property, text); - g_free (text); glade_editor_property_load (property, property->property->widget); } -static void -glade_editor_property_changed_text_view (GtkTextBuffer *buffer, - GladeEditorProperty *property) +static gboolean +glade_editor_entry_focus_out (GtkWidget *entry, + GdkEventFocus *event, + GladeEditorProperty *property) { - GtkTextIter start; - GtkTextIter end; - gchar *text; + glade_editor_property_changed_text (entry, property); + return FALSE; +} - g_return_if_fail (property != NULL); +static gboolean +glade_editor_text_view_focus_out (GtkTextView *view, + GdkEventFocus *event, + GladeEditorProperty *property) +{ + gchar *text; + GtkTextBuffer *buffer; + GtkTextIter start, end; + + g_return_val_if_fail (property != NULL, FALSE); if (property->property->loading) - return; + return FALSE; + + buffer = gtk_text_view_get_buffer (view); gtk_text_buffer_get_iter_at_offset (buffer, &start, 0); gtk_text_buffer_get_iter_at_offset (buffer, &end, gtk_text_buffer_get_char_count (buffer)); text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); - glade_editor_property_changed_text_common (property->property, text); - g_free (text); - + glade_editor_property_load (property, property->property->widget); + return FALSE; } static void @@ -420,31 +429,33 @@ glade_editor_property_changed_unichar (GtkWidget *entry, GValue val = { 0, }; guint len; gchar *text; - gunichar unich; + gunichar unich = '\0'; g_return_if_fail (property != NULL); if (property->property->loading) return; - text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); - len = g_utf8_strlen (text, -1); - g_debug (("The lenght of the string is: %d\n", len)); - unich = g_utf8_get_char (text); + if ((text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1)) != NULL) + { + len = g_utf8_strlen (text, -1); + g_debug (("The lenght of the string is: %d\n", len)); + unich = g_utf8_get_char (text); + g_free (text); + } g_value_init (&val, G_TYPE_UINT); g_value_set_uint (&val, unich); glade_command_set_property (property->property, &val); - + g_value_unset (&val); - g_free (text); - glade_editor_property_load (property, property->property->widget); } -static void glade_editor_property_delete_unichar (GtkEditable *editable, - gint start_pos, - gint end_pos) +static void +glade_editor_property_delete_unichar (GtkEditable *editable, + gint start_pos, + gint end_pos) { gtk_editable_select_region (editable, 0, -1); g_signal_stop_emission_by_name (G_OBJECT (editable), "delete_text"); @@ -734,25 +745,28 @@ glade_editor_create_input_text (GladeEditorProperty *property) entry = gtk_entry_new (); - g_signal_connect (G_OBJECT (entry), "changed", + g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (glade_editor_property_changed_text), property); + + g_signal_connect (G_OBJECT (entry), "focus-out-event", + G_CALLBACK (glade_editor_entry_focus_out), + property); return entry; } else { + GtkTextView *view; GtkTextBuffer *buffer; - GtkWidget *view; - view = gtk_text_view_new (); - gtk_text_view_set_editable (GTK_TEXT_VIEW (view), TRUE); + view = GTK_TEXT_VIEW (gtk_text_view_new ()); + buffer = gtk_text_view_get_buffer (view); - buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + gtk_text_view_set_editable (view, TRUE); - g_signal_connect_data (G_OBJECT (buffer), "changed", - G_CALLBACK (glade_editor_property_changed_text_view), - property, NULL, 0); - - return view; + g_signal_connect (G_OBJECT (view), "focus-out-event", + G_CALLBACK (glade_editor_text_view_focus_out), + property); + return GTK_WIDGET (view); } return NULL; @@ -869,8 +883,13 @@ glade_editor_create_item_label (GladePropertyClass *class) static void glade_editor_table_attach (GtkWidget *table, GtkWidget *child, gint pos, gint row) { - gtk_table_attach_defaults (GTK_TABLE (table), child, - pos, pos+1, row, row +1); +/* gtk_table_attach_defaults (GTK_TABLE (table), child, */ +/* pos, pos+1, row, row +1); */ + gtk_table_attach (GTK_TABLE (table), child, + pos, pos+1, row, row +1, + pos ? GTK_EXPAND | GTK_FILL : GTK_SHRINK, + GTK_EXPAND | GTK_FILL, + 2, 0); } @@ -937,7 +956,7 @@ glade_editor_table_append_item (GladeEditorTable *table, } static void -glade_editor_table_append_standard_fields (GladeEditorTable *table) +glade_editor_table_append_name_field (GladeEditorTable *table) { GtkWidget *gtk_table; GtkWidget *label; @@ -957,6 +976,16 @@ glade_editor_table_append_standard_fields (GladeEditorTable *table) glade_editor_table_attach (gtk_table, label, 0, table->rows); glade_editor_table_attach (gtk_table, entry, 1, table->rows); table->rows++; +} + +static void +glade_editor_table_append_class_field (GladeEditorTable *table) +{ + GtkWidget *gtk_table; + GtkWidget *label; + GtkWidget *entry; + + gtk_table = table->table_widget; /* Class */ label = gtk_label_new (_("Class :")); @@ -995,7 +1024,9 @@ glade_editor_table_append_items (GladeEditorTable *table, continue; else if (type == TABLE_TYPE_COMMON && property_class->common == FALSE) continue; - + else if (type == TABLE_TYPE_GENERAL && property_class->common == TRUE) + continue; + property = glade_editor_table_append_item (table, property_class); if (property != NULL) new_list = g_list_prepend (new_list, property); @@ -1060,8 +1091,13 @@ glade_editor_table_create (GladeEditor *editor, table->editor = editor; table->glade_widget_class = class; table->type = type; + if (type == TABLE_TYPE_GENERAL) - glade_editor_table_append_standard_fields (table); + { + glade_editor_table_append_name_field (table); + glade_editor_table_append_class_field (table); + } + if (!glade_editor_table_append_items (table, class, &table->properties, type)) return NULL; @@ -1397,12 +1433,13 @@ glade_editor_property_load_text (GladeEditorProperty *property) GtkTextBuffer *buffer; const gchar *text; - text = g_value_get_string (property->property->value); - buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (property->input)); - - gtk_text_buffer_set_text (buffer, - text, - g_utf8_strlen (text, -1)); + if ((text = g_value_get_string (property->property->value)) != NULL) + { + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (property->input)); + gtk_text_buffer_set_text (buffer, + text, + g_utf8_strlen (text, -1)); + } } else { g_warning ("Invalid Text Widget type."); } @@ -1503,7 +1540,10 @@ glade_editor_load_packing_page (GladeEditor *editor, GladeWidget *widget) /* Free the old structs */ if (old) + { + g_object_unref (G_OBJECT (old->table_widget)); g_free (old); + } for (list = old_props; list; list = list->next) g_free (list->data); old_props = NULL; @@ -1576,8 +1616,9 @@ glade_editor_load_widget (GladeEditor *editor, GladeWidget *widget) editor->loading = TRUE; /* Load each GladeEditorProperty */ - table = glade_editor_get_table_from_class (editor, class, FALSE); - gtk_entry_set_text (GTK_ENTRY (table->name_entry), widget->name); + table = glade_editor_get_table_from_class (editor, class, TABLE_TYPE_GENERAL); + if (table->name_entry) + gtk_entry_set_text (GTK_ENTRY (table->name_entry), widget->name); for (list = table->properties; list; list = list->next) { @@ -1586,7 +1627,7 @@ glade_editor_load_widget (GladeEditor *editor, GladeWidget *widget) } /* Load each GladeEditorProperty for the common tab */ - table = glade_editor_get_table_from_class (editor, class, TRUE); + table = glade_editor_get_table_from_class (editor, class, TABLE_TYPE_COMMON); for (list = table->properties; list; list = list->next) { property = list->data; @@ -1608,10 +1649,10 @@ glade_editor_load_widget (GladeEditor *editor, GladeWidget *widget) void glade_editor_add_signal (GladeEditor *editor, guint signal_id, - const char *callback_name) + const gchar *callback_name) { - const char *widget_name; - const char *signal_name; + const gchar *widget_name; + const gchar *signal_name; GType widget_type; g_return_if_fail (GLADE_IS_EDITOR (editor)); diff --git a/src/glade-editor.h b/src/glade-editor.h index 40d4d607..6e7f5832 100644 --- a/src/glade-editor.h +++ b/src/glade-editor.h @@ -22,7 +22,6 @@ typedef struct _GladeEditorTable GladeEditorTable; typedef struct _GladeEditorProperty GladeEditorProperty; typedef enum _GladeEditorTableType GladeEditorTableType; - enum _GladeEditorTableType { TABLE_TYPE_GENERAL, @@ -61,13 +60,6 @@ struct _GladeEditor * when we switch from widgets of the * same class */ - GtkTooltips *tooltips; /* The tooltips for the editor. This are not - * beeing used ATM. I wonder if they should - * go into GladeWidgetClass since they are - * different for each class or if this - * will point to the tooltips for that - * class. Oh well, we'll see - */ GtkWidget *vbox_widget; /* The editor has (at this moment) four tabs * this are pointers to the vboxes inside * each tab. The vboxes are wrapped into a diff --git a/src/glade-gtk.c b/src/glade-gtk.c index 30fd99ed..12e3de6a 100644 --- a/src/glade-gtk.c +++ b/src/glade-gtk.c @@ -79,7 +79,7 @@ glade_gtk_stock_get_type (void) { 4, "Close", "gtk-close" }, { 0, NULL, NULL } }; - etype = g_enum_register_static ("GtkTtScrollType", values); + etype = g_enum_register_static ("GladeGtkStockType", values); } return etype; } @@ -1047,23 +1047,16 @@ glade_gtk_fixed_button_press (GtkWidget *widget, gpw = glade_project_window_get (); if (gpw->add_class != NULL) { - GtkWidget *placeholder = glade_placeholder_new (); GtkWidget *new_widget; GladeWidget *new_gwidget; + GladeWidget *fixed_gwidget; GladeProperty *property; GList *selection; GValue value = { 0, }; - /* A widget type is selected in the palette. - * Create a placeholder at the mouse position and - * add a new widget of that type with a default - * size request. - */ - gtk_fixed_put(GTK_FIXED(widget), placeholder, - (gint)event->x, (gint)event->y); - - glade_command_create (gpw->add_class, - GLADE_PLACEHOLDER(placeholder), NULL); + fixed_gwidget = glade_widget_get_from_gobject (widget); + + glade_command_create (gpw->add_class, fixed_gwidget, NULL, NULL); selection = glade_project_selection_get (glade_project_window_get_active_project(gpw)); @@ -1073,6 +1066,16 @@ glade_gtk_fixed_button_press (GtkWidget *widget, g_value_init (&value, G_TYPE_INT); + property = glade_widget_get_property (new_gwidget, "x"); + property->enabled = TRUE; + g_value_set_int (&value, event->x); + glade_property_set (property, &value); + + property = glade_widget_get_property (new_gwidget, "y"); + property->enabled = TRUE; + g_value_set_int (&value, event->y); + glade_property_set (property, &value); + property = glade_widget_get_property (new_gwidget, "width-request"); property->enabled = TRUE; g_value_set_int (&value, FIXED_DEFAULT_CHILD_WIDTH); @@ -1086,7 +1089,8 @@ glade_gtk_fixed_button_press (GtkWidget *widget, /* We need to resync the editor so that width-request/height-request * are actualy enabled in the editor */ - glade_editor_load_widget (gpw->editor, gpw->editor->loaded_widget); + glade_editor_load_widget (gpw->editor, NULL); + glade_editor_load_widget (gpw->editor, new_gwidget); } return TRUE; diff --git a/src/glade-placeholder.c b/src/glade-placeholder.c index 32e520f8..374dd2c0 100644 --- a/src/glade-placeholder.c +++ b/src/glade-placeholder.c @@ -312,7 +312,7 @@ glade_placeholder_button_press (GtkWidget *widget, GdkEventButton *event) /* A widget type is selected in the palette. * Add a new widget of that type. */ - glade_command_create (gpw->add_class, placeholder, NULL); + glade_command_create (gpw->add_class, NULL, placeholder, NULL); } else { diff --git a/src/glade-popup.c b/src/glade-popup.c index 5fe66841..c59475c8 100644 --- a/src/glade-popup.c +++ b/src/glade-popup.c @@ -41,23 +41,49 @@ glade_popup_select_cb (GtkMenuItem *item, GladeWidget *widget) static void glade_popup_cut_cb (GtkMenuItem *item, GladeWidget *widget) { - glade_command_cut (widget); + GladeWidget *parent; + gboolean need_placeholder = FALSE; + + if (!widget) + { + GladeProjectWindow *gpw = glade_project_window_get (); + glade_util_ui_warn (gpw->window, _("No widget selected!")); + return; + } + + /* If this widget is parented through the GtkContainer interface, + * a placeholder will be needed. + */ + if ((parent = glade_widget_get_parent (widget)) != NULL) + need_placeholder = + glade_util_gtkcontainer_relation (parent, widget); + glade_command_cut (widget, need_placeholder); } static void glade_popup_copy_cb (GtkMenuItem *item, GladeWidget *widget) { + if (!widget) + { + GladeProjectWindow *gpw = glade_project_window_get (); + glade_util_ui_warn (gpw->window, _("No widget selected!")); + return; + } + glade_command_copy (widget); } static void glade_popup_paste_cb (GtkMenuItem *item, GladeWidget *widget) { - glade_implement_me (); - /* - * look in glade-placeholder.c (glade_placeholder_on_button_press_event - * for the "paste" operation code. - */ + if (!widget) + { + GladeProjectWindow *gpw = glade_project_window_get (); + glade_util_ui_warn (gpw->window, _("No widget selected!")); + return; + } + + glade_command_paste (widget, NULL); } static void @@ -70,17 +96,24 @@ static void glade_popup_placeholder_paste_cb (GtkMenuItem *item, GladePlaceholder *placeholder) { - glade_command_paste (placeholder); + if (!placeholder) + { + GladeProjectWindow *gpw = glade_project_window_get (); + glade_util_ui_warn (gpw->window, _("No placeholder selected!")); + return; + } + glade_command_paste (glade_placeholder_get_parent (placeholder), + 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 !!! */ + GladeWidgetClass *class; + if ((class = + g_object_get_data (G_OBJECT (item), "widget_class")) != 0) + glade_command_create (class, widget, NULL, NULL); } /* @@ -145,14 +178,11 @@ 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; + GList *list, *types, *l; 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); @@ -160,19 +190,29 @@ glade_popup_add_children (GtkWidget* popup_menu, GladeWidget *widget) 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); + if ((types = + glade_widget_class_get_derived_types (support->type)) != NULL) + { + for (l = types; l && l->data; l = l->next) + { + GladeWidgetClass *class = l->data; + GtkWidget *item = + glade_popup_append_item + (add_menu, NULL, g_type_name (class->type), + TRUE, glade_popup_add_item_cb, widget); + g_object_set_data (G_OBJECT (item), + "widget_class", class); + + } + g_list_free (types); + } } } - static GtkWidget * glade_popup_create_menu (GladeWidget *widget, gboolean add_childs) { @@ -186,8 +226,12 @@ glade_popup_create_menu (GladeWidget *widget, gboolean add_childs) glade_popup_cut_cb, widget); glade_popup_append_item (popup_menu, GTK_STOCK_COPY, NULL, TRUE, glade_popup_copy_cb, widget); - glade_popup_append_item (popup_menu, GTK_STOCK_PASTE, NULL, TRUE, - glade_popup_paste_cb, widget); + + + if (glade_util_widget_pastable (widget)) + glade_popup_append_item (popup_menu, GTK_STOCK_PASTE, NULL, TRUE, + glade_popup_paste_cb, widget); + glade_popup_append_item (popup_menu, GTK_STOCK_DELETE, NULL, TRUE, glade_popup_delete_cb, widget); @@ -225,11 +269,12 @@ glade_popup_create_placeholder_menu (GladePlaceholder *placeholder) * glade_popup_widget_pop: * @widget: * @event: + * @add_children: * * TODO: write me */ void -glade_popup_widget_pop (GladeWidget *widget, GdkEventButton *event) +glade_popup_widget_pop (GladeWidget *widget, GdkEventButton *event, gboolean add_children) { GtkWidget *popup_menu; gint button; @@ -237,7 +282,7 @@ glade_popup_widget_pop (GladeWidget *widget, GdkEventButton *event) g_return_if_fail (GLADE_IS_WIDGET (widget)); - popup_menu = glade_popup_create_menu (widget, TRUE); + popup_menu = glade_popup_create_menu (widget, add_children); if (event) { diff --git a/src/glade-popup.h b/src/glade-popup.h index a7cd3ed7..e34f5605 100644 --- a/src/glade-popup.h +++ b/src/glade-popup.h @@ -4,7 +4,7 @@ G_BEGIN_DECLS -void glade_popup_widget_pop (GladeWidget *widget, GdkEventButton *event); +void glade_popup_widget_pop (GladeWidget *widget, GdkEventButton *event, gboolean add_children); void glade_popup_placeholder_pop (GladePlaceholder *placeholder, GdkEventButton *event); G_END_DECLS diff --git a/src/glade-project-view.c b/src/glade-project-view.c index dbb9bf34..170f0e15 100644 --- a/src/glade-project-view.c +++ b/src/glade-project-view.c @@ -20,11 +20,13 @@ * Chema Celorio <chema@celorio.com> */ +#include <string.h> #include "glade.h" #include "glade-widget.h" #include "glade-project.h" #include "glade-widget-class.h" #include "glade-project-view.h" +#include "glade-popup.h" enum { @@ -129,22 +131,44 @@ glade_project_view_find_iter_by_widget (GtkTreeModel *model, GladeWidget *findme) { GtkTreeIter iter; - GtkTreeIter *retval; if (!gtk_tree_model_get_iter_root (model, &iter)) { - g_warning ("Could not find first widget."); return NULL; } + return glade_project_view_find_iter (model, &iter, findme); +} - retval = glade_project_view_find_iter (model, &iter, findme); - - if (!retval) - g_warning ("Could not find iterator for %s\n", findme->name); +static GList * +glade_project_view_list_child_iters (GtkTreeStore *model, + GladeWidget *parent) +{ + GList *children, *l, *child_iters = NULL; - return retval; + if ((children = glade_widget_class_container_get_all_children + (parent->widget_class, parent->object)) != NULL) + { + for (l = children; l && l->data; l = l->next) + { + GObject *object = l->data; + GladeWidget *gwidget; + if ((gwidget = glade_widget_get_from_gobject (object)) != NULL) + { + GtkTreeIter *iter; + + if ((iter = glade_project_view_find_iter_by_widget + (GTK_TREE_MODEL (model), gwidget)) != NULL) + { + child_iters = g_list_prepend (child_iters, iter); + } + } + } + g_list_free (children); + } + return g_list_reverse (child_iters); } + static void glade_project_view_widget_name_changed (GladeProjectView *view, GladeWidget *findme) @@ -178,8 +202,8 @@ glade_project_view_populate_model_real (GtkTreeStore *model, GtkTreeIter *parent_iter, gboolean add_childs) { - GList *list; - GtkTreeIter iter; + GList *children, *list; + GtkTreeIter iter; list = g_list_copy (widgets); list = g_list_reverse (list); @@ -187,28 +211,26 @@ glade_project_view_populate_model_real (GtkTreeStore *model, { GladeWidget *widget; - widget = glade_widget_get_from_gobject (list->data); - if (widget) + if ((widget = glade_widget_get_from_gobject (list->data)) != NULL) { 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); - if (add_childs && GTK_IS_CONTAINER (list->data)) - { - GList *children; - GtkTreeIter *copy = NULL; - - copy = gtk_tree_iter_copy (&iter); - children = gtk_container_get_children (GTK_CONTAINER (list->data)); - glade_project_view_populate_model_real (model, children, copy, TRUE); - gtk_tree_iter_free (copy); - g_list_free (children); + if (add_childs && + (children = glade_widget_class_container_get_all_children + (widget->widget_class, widget->object)) != NULL) + { + GtkTreeIter *copy = NULL; + + copy = gtk_tree_iter_copy (&iter); + glade_project_view_populate_model_real + (model, children, copy, TRUE); + gtk_tree_iter_free (copy); + + g_list_free (children); + } } } - g_list_free (list); } @@ -227,7 +249,7 @@ glade_project_view_populate_model (GladeProjectView *view) for (list = project->objects; list; list = list->next) { GObject *object = G_OBJECT (list->data); - if (GTK_WIDGET_TOPLEVEL (object)) + if (GTK_IS_WIDGET (object) && GTK_WIDGET_TOPLEVEL (object)) toplevels = g_list_append (toplevels, object); } @@ -243,11 +265,12 @@ glade_project_view_add_item (GladeProjectView *view, GladeWidget *widget) { GladeWidgetClass *class; - GladeWidget *parent; + GladeWidget *parent; GtkTreeStore *model; - GtkTreeIter iter; - GtkTreeIter *parent_iter = NULL; - + GtkTreeIter iter; + GtkTreeIter *parent_iter = NULL, *child_iter; + GList *child_iters, *children, *l; + g_return_if_fail (widget != NULL); class = glade_widget_get_class (widget); @@ -265,11 +288,25 @@ glade_project_view_add_item (GladeProjectView *view, gtk_tree_store_append (model, &iter, parent_iter); gtk_tree_store_set (model, &iter, WIDGET_COLUMN, widget, -1); - - /* - XXX Add find any children and shuffle them around in the tree view. - */ + /* Remove all children */ + if ((child_iters = + glade_project_view_list_child_iters (model, widget)) != NULL) + { + for (l = child_iters; l && l->data; l = l->next) + { + child_iter = l->data; + gtk_tree_store_remove (model, child_iter); + } + } + /* Repopulate these children properly. + */ + if ((children = glade_widget_class_container_get_all_children + (widget->widget_class, widget->object)) != NULL) + { + glade_project_view_populate_model_real (model, children, &iter, TRUE); + g_list_free (children); + } view->updating_selection = TRUE; glade_project_selection_set (widget->project, @@ -292,8 +329,8 @@ glade_project_view_remove_item (GladeProjectView *view, model = GTK_TREE_MODEL (view->model); - iter = glade_project_view_find_iter_by_widget (model, widget); - gtk_tree_store_remove (view->model, iter); + if ((iter = glade_project_view_find_iter_by_widget (model, widget)) != NULL) + gtk_tree_store_remove (view->model, iter); } /** @@ -430,6 +467,42 @@ glade_project_view_item_activated_cb (GtkTreeView *view, } } +static gint +glade_project_view_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + GladeProjectView *view) +{ + GtkTreeView *tree_view = GTK_TREE_VIEW (widget); + GtkTreePath *path = NULL; + + if (event->button == 3 && + event->window == gtk_tree_view_get_bin_window (tree_view)) + { + if (gtk_tree_view_get_path_at_pos + (tree_view, event->x, event->y, + &path, NULL, NULL, NULL) && path != NULL) + { + GtkTreeIter iter; + GladeWidget *widget = NULL; + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (view->model), + &iter, path)) + { + /* Alright, now we can obtain the widget from the iter. + */ + gtk_tree_model_get (GTK_TREE_MODEL (view->model), &iter, + WIDGET_COLUMN, &widget, -1); + if (widget != NULL) + { + glade_popup_widget_pop (widget, event, FALSE); + } + } + gtk_tree_path_free (path); + } + return TRUE; + } + return FALSE; +} + static void glade_project_view_cell_function (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, @@ -454,11 +527,13 @@ glade_project_view_cell_function (GtkTreeViewColumn *tree_column, if (is_icon) { - if (gtk_image_get_storage_type GTK_IMAGE (widget->widget_class->icon) != GTK_IMAGE_PIXBUF) + if (gtk_image_get_storage_type + (GTK_IMAGE (widget->widget_class->icon)) != GTK_IMAGE_PIXBUF) return; g_object_set (G_OBJECT (cell), "pixbuf", - gtk_image_get_pixbuf (GTK_IMAGE (widget->widget_class->icon)), NULL); + gtk_image_get_pixbuf + (GTK_IMAGE (widget->widget_class->icon)), NULL); } else { @@ -490,11 +565,24 @@ glade_project_view_add_columns (GtkTreeView *view) gtk_tree_view_append_column (view, column); } +static gint +glade_project_view_sort_func (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) +{ + GladeWidget *widget_a, *widget_b; + gtk_tree_model_get (model, a, WIDGET_COLUMN, &widget_a, -1); + gtk_tree_model_get (model, b, WIDGET_COLUMN, &widget_b, -1); + return strcmp (glade_widget_get_name (widget_a), + glade_widget_get_name (widget_b)); +} + static void glade_project_view_init (GladeProjectView *view) { GtkTreeSelection *selection; - + view->selected_widget = NULL; view->project = NULL; view->add_widget_signal_id = 0; @@ -502,6 +590,14 @@ glade_project_view_init (GladeProjectView *view) view->model = gtk_tree_store_new (N_COLUMNS, G_TYPE_POINTER); glade_project_view_populate_model (view); + + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (view->model), + 0, GTK_SORT_ASCENDING); + + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (view->model), 0, + glade_project_view_sort_func, + NULL, NULL); + view->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (view->model)); /* the view now holds a reference, we can get rid of our own */ @@ -517,6 +613,9 @@ glade_project_view_init (GladeProjectView *view) G_CALLBACK (glade_project_view_selection_changed_cb), view, NULL, 0); + g_signal_connect (G_OBJECT (view->tree_view), "button-press-event", + G_CALLBACK (glade_project_view_button_press_cb), view); + view->updating_selection = FALSE; } @@ -580,8 +679,8 @@ glade_project_view_new (GladeProjectViewType type) else view->is_list = FALSE; - gtk_container_add (GTK_CONTAINER (view), view->tree_view); - + gtk_container_add (GTK_CONTAINER (view), view->tree_view); + return view; } diff --git a/src/glade-project-window.c b/src/glade-project-window.c index 8085e747..8f0d9912 100644 --- a/src/glade-project-window.c +++ b/src/glade-project-window.c @@ -331,7 +331,7 @@ do_close (GladeProjectWindow *gpw, GladeProject *project) for (list = project->objects; list; list = list->next) { GObject *object = list->data; - if (GTK_WIDGET_TOPLEVEL (object)) + if (GTK_IS_WIDGET (object) && GTK_WIDGET_TOPLEVEL (object)) gtk_widget_destroy (GTK_WIDGET(object)); } @@ -439,13 +439,26 @@ gpw_cut_cb (void) gpw = glade_project_window_get (); list = glade_project_selection_get (gpw->active_project); + /* TODO: support multiple selected items */ if (list != NULL && list->next == NULL) { GladeWidget *widget = glade_widget_get_from_gobject (GTK_WIDGET (list->data)); + GladeWidget *parent; - if (widget) - glade_command_cut (widget); + gboolean need_placeholder = FALSE; + + if (!widget) + { + GladeProjectWindow *gpw = glade_project_window_get (); + glade_util_ui_warn (gpw->window, _("No widget selected!")); + return; + } + + if ((parent = glade_widget_get_parent (widget)) != NULL) + need_placeholder = + glade_util_gtkcontainer_relation (parent, widget); + glade_command_cut (widget, need_placeholder); } } @@ -453,13 +466,39 @@ static void gpw_paste_cb (void) { GladeProjectWindow *gpw; - GList *selection; + GList *list; gpw = glade_project_window_get (); + list = glade_project_selection_get (gpw->active_project); + + /* TODO: support multiple selected items */ + if (list != NULL && list->next == NULL) + { + GladePlaceholder *placeholder = NULL; + GladeWidget *widget; + - selection = glade_project_selection_get (gpw->active_project); - if (selection != NULL && selection->next == NULL && GLADE_IS_PLACEHOLDER (selection->data)) - glade_command_paste (GLADE_PLACEHOLDER (selection->data)); + if (GLADE_IS_PLACEHOLDER (list->data)) + { + placeholder = list->data; + widget = glade_placeholder_get_parent (placeholder); + } + else + { + widget = glade_widget_get_from_gobject (G_OBJECT (list->data)); + } + + if (!widget) + { + GladeProjectWindow *gpw = glade_project_window_get (); + glade_util_ui_warn (gpw->window, + _("No widget or placeholder selected!")); + return; + } + + if (glade_util_widget_pastable (widget)) + glade_command_paste (widget, placeholder); + } } static void @@ -542,7 +581,7 @@ gpw_palette_button_clicked (GladePalette *palette, gpointer not_used) /* class may be NULL if the selector was pressed */ if (class && g_type_is_a (class->type, GTK_TYPE_WINDOW)) { - glade_command_create (class, NULL, gpw->active_project); + glade_command_create (class, NULL, NULL, gpw->active_project); gpw->add_class = NULL; } else @@ -719,7 +758,7 @@ gpw_create_widget_tree (GladeProjectWindow *gpw) glade_project_view_set_project (view, gpw->active_project); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view), - GTK_POLICY_NEVER, GTK_POLICY_NEVER); + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (widget_tree), GTK_WIDGET (view)); @@ -1317,9 +1356,9 @@ gpw_project_selection_changed_cb (GladeProject *project, list = glade_project_selection_get (project); num = g_list_length (list); if (num == 1 && !GLADE_IS_PLACEHOLDER (list->data)) - glade_editor_load_widget (gpw->editor, - glade_widget_get_from_gobject - (GTK_WIDGET (list->data))); + glade_editor_load_widget + (gpw->editor, + glade_widget_get_from_gobject (list->data)); else glade_editor_load_widget (gpw->editor, NULL); } @@ -1454,7 +1493,7 @@ glade_project_window_change_menu_label (GladeProjectWindow *gpw, bin = GTK_BIN (gtk_item_factory_get_item (gpw->item_factory, path)); label = GTK_LABEL (gtk_bin_get_child (bin)); - + if (prefix == NULL) { gtk_label_set_text_with_mnemonic (label, suffix); diff --git a/src/glade-project.c b/src/glade-project.c index 69a0c8c8..bf95de42 100644 --- a/src/glade-project.c +++ b/src/glade-project.c @@ -742,9 +742,11 @@ glade_project_new_from_interface (GladeInterface *interface) g_warning ("Failed to read a <widget> tag"); continue; } - project->objects = g_list_prepend (project->objects, - glade_widget_get_object(widget)); - g_object_ref (glade_widget_get_object(widget)); + glade_project_add_object (project, widget->object); + +/* project->objects = g_list_prepend (project->objects, */ +/* glade_widget_get_object(widget)); */ +/* g_object_ref (glade_widget_get_object(widget)); */ } return project; diff --git a/src/glade-property-class.c b/src/glade-property-class.c index a16e9bbe..bf9b6706 100644 --- a/src/glade-property-class.c +++ b/src/glade-property-class.c @@ -409,7 +409,7 @@ glade_property_class_make_gvalue_from_string (GladePropertyClass *property_class GValue *value = g_new0 (GValue, 1); g_value_init (value, property_class->pspec->value_type); - + if (G_IS_PARAM_SPEC_ENUM(property_class->pspec)) { gint eval = glade_property_class_make_enum_from_string @@ -591,6 +591,10 @@ glade_property_class_update_from_node (GladeXmlNode *node, { class->pspec = glade_utils_get_pspec_from_funcname (buff); g_free (buff); + + /* ... get the tooltip from the pspec ... */ + if (class->pspec) + class->tooltip = g_strdup (g_param_spec_get_blurb (class->pspec)); } /* ...and the tooltip */ @@ -623,7 +627,7 @@ glade_property_class_update_from_node (GladeXmlNode *node, class->common = glade_xml_get_property_boolean (node, GLADE_TAG_COMMON, FALSE); class->optional = glade_xml_get_property_boolean (node, GLADE_TAG_OPTIONAL, FALSE); class->query = glade_xml_get_property_boolean (node, GLADE_TAG_QUERY, FALSE); - + if (class->optional) class->optional_default = glade_xml_get_property_boolean (node, GLADE_TAG_OPTIONAL_DEFAULT, FALSE); diff --git a/src/glade-property.c b/src/glade-property.c index 9c722788..dc41ff6d 100644 --- a/src/glade-property.c +++ b/src/glade-property.c @@ -216,8 +216,15 @@ glade_property_sync (GladeProperty *property) * updating the selection if the widget was selected. */ GList *selection; - gboolean reselect = FALSE; - if (property->widget->project) + gboolean reselect = FALSE; + gboolean inproject = + property->widget->project ? + (glade_project_get_widget_by_name + (property->widget->project, + property->widget->name) ? TRUE : FALSE) : FALSE; + + + if (inproject) { if ((selection = glade_project_selection_get (property->widget->project)) != NULL && @@ -235,7 +242,7 @@ glade_property_sync (GladeProperty *property) glade_widget_rebuild (property->widget); - if (property->widget->project) + if (inproject) { glade_project_add_object (property->widget->project, glade_widget_get_object (property->widget)); diff --git a/src/glade-signal-editor.c b/src/glade-signal-editor.c index 6cb89236..8eb61abb 100644 --- a/src/glade-signal-editor.c +++ b/src/glade-signal-editor.c @@ -38,14 +38,23 @@ enum COLUMN_SIGNAL, COLUMN_HANDLER, COLUMN_AFTER, + COLUMN_USERDATA, + COLUMN_LOOKUP, + COLUMN_USERDATA_SLOT, + COLUMN_LOOKUP_VISIBLE, COLUMN_AFTER_VISIBLE, COLUMN_HANDLER_EDITABLE, + COLUMN_USERDATA_EDITABLE, COLUMN_SLOT, /* if this row contains a "<Type...>" label */ COLUMN_BOLD, NUM_COLUMNS }; +#define HANDLER_DEFAULT "<Type the signal's handler here>" +#define USERDATA_DEFAULT "<Type the object's name or symbol to lookup here>" + + static void glade_signal_editor_after_toggled (GtkCellRendererToggle *cell, gchar *path_str, @@ -58,13 +67,20 @@ glade_signal_editor_after_toggled (GtkCellRendererToggle *cell, GladeSignal *old_signal; GladeSignal *new_signal; GtkTreePath *path = gtk_tree_path_new_from_string (path_str); - char *signal_name; - char *handler; - gboolean after; + gchar *signal_name; + gchar *handler; + gchar *userdata; + gboolean lookup; + gboolean after; /* get toggled iter */ gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, COLUMN_SIGNAL, &signal_name, COLUMN_HANDLER, &handler, COLUMN_AFTER, &after, -1); + gtk_tree_model_get (model, &iter, + COLUMN_SIGNAL, &signal_name, + COLUMN_HANDLER, &handler, + COLUMN_USERDATA,&userdata, + COLUMN_LOOKUP, &lookup, + COLUMN_AFTER, &after, -1); if (signal_name == NULL) { if (!gtk_tree_model_iter_parent (model, &iter_parent, &iter)) @@ -74,10 +90,10 @@ glade_signal_editor_after_toggled (GtkCellRendererToggle *cell, g_assert (signal_name != NULL); } - old_signal = glade_signal_new (signal_name, handler, after); - new_signal = glade_signal_new (signal_name, handler, !after); + old_signal = glade_signal_new (signal_name, handler, userdata, lookup, after); + new_signal = glade_signal_new (signal_name, handler, userdata, lookup, !after); - /* TODO: Action not yet undoable */ + /* XXX TODO: Action not yet undoable */ glade_widget_change_signal_handler (editor->widget, old_signal, new_signal); gtk_tree_store_set (GTK_TREE_STORE (model), &iter, COLUMN_AFTER, !after, -1); @@ -86,8 +102,60 @@ glade_signal_editor_after_toggled (GtkCellRendererToggle *cell, gtk_tree_path_free (path); g_free (signal_name); g_free (handler); + g_free (userdata); } +static void +glade_signal_editor_lookup_toggled (GtkCellRendererToggle *cell, + gchar *path_str, + gpointer data) +{ + GladeSignalEditor *editor = (GladeSignalEditor*) data; + GtkTreeModel *model = GTK_TREE_MODEL (editor->model); + GtkTreeIter iter; + GtkTreeIter iter_parent; + GladeSignal *old_signal; + GladeSignal *new_signal; + GtkTreePath *path = gtk_tree_path_new_from_string (path_str); + gchar *signal_name; + gchar *handler; + gchar *userdata; + gboolean lookup; + gboolean after; + + /* get toggled iter */ + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + COLUMN_SIGNAL, &signal_name, + COLUMN_HANDLER, &handler, + COLUMN_USERDATA,&userdata, + COLUMN_LOOKUP, &lookup, + COLUMN_AFTER, &after, -1); + if (signal_name == NULL) + { + if (!gtk_tree_model_iter_parent (model, &iter_parent, &iter)) + g_assert (FALSE); + + gtk_tree_model_get (model, &iter_parent, COLUMN_SIGNAL, &signal_name, -1); + g_assert (signal_name != NULL); + } + + old_signal = glade_signal_new (signal_name, handler, userdata, lookup, after); + new_signal = glade_signal_new (signal_name, handler, userdata, !lookup, after); + + /* XXX TODO: Action not yet undoable */ + glade_widget_change_signal_handler (editor->widget, old_signal, new_signal); + gtk_tree_store_set (GTK_TREE_STORE (model), &iter, COLUMN_LOOKUP, !lookup, -1); + + glade_signal_free (old_signal); + glade_signal_free (new_signal); + gtk_tree_path_free (path); + g_free (signal_name); + g_free (handler); + g_free (userdata); +} + + static gboolean glade_signal_editor_is_valid_identifier (const char *text) { @@ -115,11 +183,17 @@ append_slot (GtkTreeModel *model, GtkTreeIter *iter_signal) gtk_tree_store_append (GTK_TREE_STORE (model), &iter_new_slot, iter_signal); gtk_tree_store_set (GTK_TREE_STORE (model), &iter_new_slot, - COLUMN_HANDLER, _("<Type the signal's handler here>"), - COLUMN_AFTER, FALSE, - COLUMN_AFTER_VISIBLE, FALSE, + COLUMN_HANDLER, _(HANDLER_DEFAULT), + COLUMN_USERDATA, _(USERDATA_DEFAULT), + COLUMN_LOOKUP, FALSE, + COLUMN_LOOKUP_VISIBLE, FALSE, COLUMN_HANDLER_EDITABLE, TRUE, - COLUMN_SLOT, TRUE, -1); + COLUMN_USERDATA_EDITABLE,FALSE, + COLUMN_AFTER, FALSE, + COLUMN_AFTER_VISIBLE, FALSE, + COLUMN_SLOT, TRUE, + COLUMN_USERDATA_SLOT, TRUE, + -1); gtk_tree_model_iter_parent (model, &iter_class, iter_signal); /* mark the signal & class name as bold */ @@ -160,13 +234,22 @@ remove_slot (GtkTreeModel *model, GtkTreeIter *iter) do { - char *handler; + gchar *handler; gboolean after; gboolean slot; gboolean visible; - gtk_tree_model_get (model, &iter_next, COLUMN_HANDLER, &handler, COLUMN_AFTER, &after, COLUMN_SLOT, &slot, COLUMN_AFTER_VISIBLE, &visible, -1); - gtk_tree_store_set (GTK_TREE_STORE (model), iter, COLUMN_HANDLER, handler, COLUMN_AFTER, after, COLUMN_SLOT, slot, COLUMN_AFTER_VISIBLE, visible, -1); + gtk_tree_model_get (model, &iter_next, + COLUMN_HANDLER, &handler, + COLUMN_AFTER, &after, + COLUMN_SLOT, &slot, + COLUMN_AFTER_VISIBLE, &visible, -1); + + gtk_tree_store_set (GTK_TREE_STORE (model), iter, + COLUMN_HANDLER, handler, + COLUMN_AFTER, after, + COLUMN_SLOT, slot, + COLUMN_AFTER_VISIBLE, visible, -1); g_free (handler); *iter = iter_next; @@ -178,35 +261,55 @@ remove_slot (GtkTreeModel *model, GtkTreeIter *iter) if (!gtk_tree_model_iter_has_child (model, &iter_signal)) { /* mark the signal & class name as normal */ - gtk_tree_store_set (GTK_TREE_STORE (model), &iter_signal, COLUMN_BOLD, FALSE, -1); - gtk_tree_store_set (GTK_TREE_STORE (model), &iter_class, COLUMN_BOLD, FALSE, -1); + gtk_tree_store_set (GTK_TREE_STORE (model), &iter_signal, + COLUMN_BOLD, FALSE, -1); + gtk_tree_store_set (GTK_TREE_STORE (model), &iter_class, + COLUMN_BOLD, FALSE, -1); } } static gboolean -is_void_signal_handler (const char *signal_handler) +is_void_signal_handler (const gchar *signal_handler) +{ + return ( signal_handler == NULL || + *signal_handler == 0 || + strcmp (signal_handler, _(HANDLER_DEFAULT)) == 0); +} + +static gboolean +is_void_user_data (const gchar *user_data) { - return (signal_handler == NULL || *signal_handler == 0 || strcmp (signal_handler, _("<Type the signal's handler here>")) == 0); + return ( user_data == NULL || + *user_data == 0 || + strcmp (user_data, _(USERDATA_DEFAULT)) == 0); } static void -glade_signal_editor_cell_edited (GtkCellRendererText *cell, - const gchar *path_str, - const gchar *new_handler, - gpointer data) +glade_signal_editor_handler_cell_edited (GtkCellRendererText *cell, + const gchar *path_str, + const gchar *new_handler, + gpointer data) { GladeWidget *glade_widget = ((GladeSignalEditor*) data)->widget; GtkTreeModel *model = GTK_TREE_MODEL (((GladeSignalEditor*) data)->model); GtkTreePath *path = gtk_tree_path_new_from_string (path_str); GtkTreeIter iter; GtkTreeIter iter_signal; - char *signal_name; - char *old_handler; - gboolean after; - gboolean slot; + gchar *signal_name; + gchar *old_handler; + gchar *userdata; + gboolean lookup; + gboolean after; + gboolean slot; gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, COLUMN_SIGNAL, &signal_name, COLUMN_HANDLER, &old_handler, COLUMN_AFTER, &after, COLUMN_SLOT, &slot, -1); + gtk_tree_model_get (model, &iter, + COLUMN_SIGNAL, &signal_name, + COLUMN_HANDLER, &old_handler, + COLUMN_USERDATA, &userdata, + COLUMN_LOOKUP, &lookup, + COLUMN_AFTER, &after, + COLUMN_SLOT, &slot, -1); if (signal_name == NULL) { @@ -226,10 +329,15 @@ glade_signal_editor_cell_edited (GtkCellRendererText *cell, /* we're adding a new handler */ if (slot && !is_void_signal_handler(new_handler)) { - GladeSignal *new_signal = glade_signal_new (signal_name, new_handler, FALSE); + GladeSignal *new_signal = glade_signal_new (signal_name, new_handler, + NULL, FALSE, FALSE); glade_command_add_signal (glade_widget, new_signal); glade_signal_free (new_signal); - gtk_tree_store_set (GTK_TREE_STORE (model), &iter, COLUMN_HANDLER, new_handler, COLUMN_AFTER_VISIBLE, TRUE, COLUMN_SLOT, FALSE, -1); + gtk_tree_store_set (GTK_TREE_STORE (model), &iter, + COLUMN_HANDLER, new_handler, + COLUMN_AFTER_VISIBLE, TRUE, + COLUMN_SLOT, FALSE, + COLUMN_USERDATA_EDITABLE,TRUE, -1); /* append a <Type...> slot */ append_slot (model, &iter_signal); @@ -238,31 +346,138 @@ glade_signal_editor_cell_edited (GtkCellRendererText *cell, /* we're removing a signal handler */ if (!slot && is_void_signal_handler(new_handler)) { - GladeSignal *old_signal = glade_signal_new (signal_name, old_handler, after); + GladeSignal *old_signal = glade_signal_new (signal_name, old_handler, + userdata, lookup, after); glade_command_remove_signal (glade_widget, old_signal); glade_signal_free (old_signal); + gtk_tree_store_set (GTK_TREE_STORE (model), &iter, + COLUMN_LOOKUP_VISIBLE, FALSE, + COLUMN_LOOKUP, FALSE, + COLUMN_USERDATA, _(USERDATA_DEFAULT), + COLUMN_USERDATA_SLOT, TRUE, + COLUMN_USERDATA_EDITABLE,FALSE, -1); + remove_slot (model, &iter); } /* we're changing a signal handler */ if (!slot && !is_void_signal_handler(new_handler)) { - /* TODO: Action not yet undoable */ - GladeSignal *old_signal = glade_signal_new (signal_name, old_handler, after); - GladeSignal *new_signal = glade_signal_new (signal_name, new_handler, after); + /* XXX TODO: Action not yet undoable */ + GladeSignal *old_signal = + glade_signal_new + (signal_name, + old_handler, + is_void_user_data(userdata) ? NULL : userdata, + lookup, + after); + GladeSignal *new_signal = + glade_signal_new + (signal_name, + new_handler, + is_void_user_data(userdata) ? NULL : userdata, + lookup, + after); glade_widget_change_signal_handler (glade_widget, old_signal, new_signal); glade_signal_free (old_signal); glade_signal_free (new_signal); - gtk_tree_store_set (GTK_TREE_STORE (model), &iter, COLUMN_HANDLER, new_handler, COLUMN_AFTER_VISIBLE, TRUE, COLUMN_SLOT, FALSE, -1); + gtk_tree_store_set (GTK_TREE_STORE (model), &iter, + COLUMN_HANDLER, new_handler, + COLUMN_AFTER_VISIBLE, TRUE, + COLUMN_SLOT, FALSE, + COLUMN_USERDATA_EDITABLE,TRUE, -1); } gtk_tree_path_free (path); g_free (signal_name); g_free (old_handler); + g_free (userdata); +} + + + +static void +glade_signal_editor_userdata_cell_edited (GtkCellRendererText *cell, + const gchar *path_str, + const gchar *new_userdata, + gpointer data) +{ + GladeWidget *glade_widget = ((GladeSignalEditor*) data)->widget; + GtkTreeModel *model = GTK_TREE_MODEL (((GladeSignalEditor*) data)->model); + GtkTreePath *path = gtk_tree_path_new_from_string (path_str); + GtkTreeIter iter; + GtkTreeIter iter_signal; + gchar *signal_name; + gchar *old_userdata; + gchar *handler; + gboolean after; + gboolean lookup; + + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + COLUMN_SIGNAL, &signal_name, + COLUMN_HANDLER, &handler, + COLUMN_USERDATA, &old_userdata, + COLUMN_LOOKUP, &lookup, + COLUMN_AFTER, &after, -1); + + if (signal_name == NULL) + { + if (!gtk_tree_model_iter_parent (model, &iter_signal, &iter)) + g_assert (FALSE); + + gtk_tree_model_get (model, &iter_signal, COLUMN_SIGNAL, &signal_name, -1); + g_assert (signal_name != NULL); + } + else + iter_signal = iter; + + + /* We are removing userdata */ + if (is_void_user_data(new_userdata)) + { + gtk_tree_store_set (GTK_TREE_STORE (model), &iter, + COLUMN_USERDATA_SLOT, TRUE, + COLUMN_USERDATA, _(USERDATA_DEFAULT), + COLUMN_LOOKUP, FALSE, + COLUMN_LOOKUP_VISIBLE, FALSE, -1); + } + else /* we're changing a signal handler's userdata */ + + { + /* XXX TODO: Action not yet undoable */ + GladeSignal *old_signal = + glade_signal_new + (signal_name, + handler, + is_void_user_data(old_userdata) ? NULL : old_userdata, + lookup, + after); + GladeSignal *new_signal = glade_signal_new (signal_name, + handler, + new_userdata, + lookup, + after); + + glade_widget_change_signal_handler (glade_widget, old_signal, new_signal); + + glade_signal_free (old_signal); + glade_signal_free (new_signal); + + gtk_tree_store_set (GTK_TREE_STORE (model), &iter, + COLUMN_USERDATA_SLOT, FALSE, + COLUMN_USERDATA, new_userdata, + COLUMN_LOOKUP_VISIBLE, TRUE, + -1); + } + gtk_tree_path_free (path); + g_free (signal_name); + g_free (handler); + g_free (old_userdata); } static void @@ -281,7 +496,22 @@ glade_signal_editor_construct_signals_list (GladeSignalEditor *editor) GtkCellRenderer *renderer; GtkTreeModel *model; - editor->model = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + editor->model = gtk_tree_store_new + (NUM_COLUMNS, + G_TYPE_STRING, /* Signal value */ + G_TYPE_STRING, /* Handler value */ + G_TYPE_BOOLEAN, /* After value */ + G_TYPE_STRING, /* User data value */ + G_TYPE_BOOLEAN, /* module lookup string for + * user data */ + G_TYPE_BOOLEAN, /* Whether userdata is a slot */ + G_TYPE_BOOLEAN, /* Lookup visibility */ + G_TYPE_BOOLEAN, /* After visibility */ + G_TYPE_BOOLEAN, /* Handler editable */ + G_TYPE_BOOLEAN, /* Userdata editable */ + G_TYPE_BOOLEAN, /* New slot */ + G_TYPE_BOOLEAN); /* Mark with bold */ + model = GTK_TREE_MODEL (editor->model); view_widget = gtk_tree_view_new_with_model (model); @@ -292,25 +522,67 @@ glade_signal_editor_construct_signals_list (GladeSignalEditor *editor) g_signal_connect(view, "row-activated", (GCallback) row_activated, NULL); - /* signal column */ + /************************ signal column ************************/ renderer = gtk_cell_renderer_text_new (); g_object_set (G_OBJECT (renderer), "weight", PANGO_WEIGHT_BOLD, NULL); - column = gtk_tree_view_column_new_with_attributes (_("Signal"), renderer, "text", COLUMN_SIGNAL, "weight-set", COLUMN_BOLD, NULL); + column = gtk_tree_view_column_new_with_attributes + (_("Signal"), renderer, "text", COLUMN_SIGNAL, "weight-set", COLUMN_BOLD, NULL); + gtk_tree_view_append_column (view, column); + + /************************ handler column ************************/ + renderer = gtk_cell_renderer_text_new (); + g_object_set (G_OBJECT (renderer), + "style", PANGO_STYLE_ITALIC, + "foreground", "Gray", NULL); + + g_signal_connect (renderer, "edited", + G_CALLBACK (glade_signal_editor_handler_cell_edited), editor); + + column = gtk_tree_view_column_new_with_attributes + (_("Handler"), renderer, + "text", COLUMN_HANDLER, + "style_set", COLUMN_SLOT, + "foreground_set", COLUMN_SLOT, + "editable", COLUMN_HANDLER_EDITABLE, NULL); + gtk_tree_view_append_column (view, column); - /* handler column */ + /************************ userdata column ************************/ renderer = gtk_cell_renderer_text_new (); - g_object_set (G_OBJECT (renderer), "style", PANGO_STYLE_ITALIC, "foreground", "Gray", NULL); - g_signal_connect (renderer, "edited", G_CALLBACK (glade_signal_editor_cell_edited), editor); - column = gtk_tree_view_column_new_with_attributes (_("Handler"), renderer, - "text", COLUMN_HANDLER, "style_set", COLUMN_SLOT, - "foreground_set", COLUMN_SLOT, "editable", COLUMN_HANDLER_EDITABLE, NULL); + g_object_set (G_OBJECT (renderer), + "style", PANGO_STYLE_ITALIC, + "foreground", "Gray", NULL); + + g_signal_connect (renderer, "edited", + G_CALLBACK (glade_signal_editor_userdata_cell_edited), editor); + column = gtk_tree_view_column_new_with_attributes + (_("User data"), renderer, + "text", COLUMN_USERDATA, + "style_set", COLUMN_USERDATA_SLOT, + "foreground_set", COLUMN_USERDATA_SLOT, + "editable", COLUMN_USERDATA_EDITABLE, NULL); + gtk_tree_view_append_column (view, column); - /* after column */ + /************************ lookup column ************************/ + renderer = gtk_cell_renderer_toggle_new (); + g_signal_connect (renderer, "toggled", + G_CALLBACK (glade_signal_editor_lookup_toggled), editor); + column = gtk_tree_view_column_new_with_attributes + (_("Lookup"), renderer, + "active", COLUMN_LOOKUP, + "visible", COLUMN_LOOKUP_VISIBLE, NULL); + + gtk_tree_view_append_column (view, column); + + /************************ after column ************************/ renderer = gtk_cell_renderer_toggle_new (); - g_signal_connect (renderer, "toggled", G_CALLBACK (glade_signal_editor_after_toggled), editor); - column = gtk_tree_view_column_new_with_attributes (_("After"), renderer, "active", COLUMN_AFTER, "visible", COLUMN_AFTER_VISIBLE, NULL); + g_signal_connect (renderer, "toggled", + G_CALLBACK (glade_signal_editor_after_toggled), editor); + column = gtk_tree_view_column_new_with_attributes + (_("After"), renderer, + "active", COLUMN_AFTER, + "visible", COLUMN_AFTER_VISIBLE, NULL); gtk_tree_view_append_column (view, column); return view_widget; @@ -387,7 +659,7 @@ glade_signal_editor_load_widget (GladeSignalEditor *editor, GladeWidget *widget) { GList *list; - const char *last_type = ""; + const gchar *last_type = ""; GtkTreeIter iter; GtkTreeIter parent_class; GtkTreeIter parent_signal; @@ -405,19 +677,24 @@ glade_signal_editor_load_widget (GladeSignalEditor *editor, if (!widget) return; + /* Loop over every signal type + */ for (list = editor->class->signals; list; list = list->next) { GladeWidgetClassSignal *signal = (GladeWidgetClassSignal *) list->data; + /* Add class name that this signal belongs to. + */ if (strcmp(last_type, signal->type)) { gtk_tree_store_append (editor->model, &parent_class, NULL); - gtk_tree_store_set (editor->model, &parent_class, - COLUMN_SIGNAL, signal->type, - COLUMN_AFTER_VISIBLE, FALSE, - COLUMN_HANDLER_EDITABLE, FALSE, - COLUMN_SLOT, FALSE, - COLUMN_BOLD, FALSE, -1); + gtk_tree_store_set (editor->model, &parent_class, + COLUMN_SIGNAL, signal->type, + COLUMN_AFTER_VISIBLE, FALSE, + COLUMN_HANDLER_EDITABLE, FALSE, + COLUMN_USERDATA_EDITABLE,FALSE, + COLUMN_SLOT, FALSE, + COLUMN_BOLD, FALSE, -1); last_type = signal->type; } @@ -425,54 +702,96 @@ glade_signal_editor_load_widget (GladeSignalEditor *editor, signals = glade_widget_list_signal_handlers (widget, signal->name); if (!signals || signals->len == 0) - gtk_tree_store_set (editor->model, &parent_signal, - COLUMN_SIGNAL, signal->name, - COLUMN_HANDLER, _("<Type the signal's handler here>"), - COLUMN_AFTER, FALSE, - COLUMN_HANDLER_EDITABLE, TRUE, - COLUMN_AFTER_VISIBLE, FALSE, - COLUMN_SLOT, TRUE, -1); + { + gtk_tree_store_set + (editor->model, &parent_signal, + COLUMN_SIGNAL, signal->name, + COLUMN_HANDLER, _(HANDLER_DEFAULT), + COLUMN_AFTER, FALSE, + COLUMN_USERDATA, _(USERDATA_DEFAULT), + COLUMN_LOOKUP, FALSE, + COLUMN_LOOKUP_VISIBLE, FALSE, + COLUMN_HANDLER_EDITABLE, TRUE, + COLUMN_USERDATA_EDITABLE,FALSE, + COLUMN_AFTER_VISIBLE, FALSE, + COLUMN_SLOT, TRUE, + COLUMN_USERDATA_SLOT, TRUE, + -1); + } else { - size_t i; + gint i; GtkTreePath *path_parent_class; - GladeSignal *widget_signal = (GladeSignal*) g_ptr_array_index (signals, 0); + GladeSignal *widget_signal = + (GladeSignal*) g_ptr_array_index (signals, 0); /* mark the class of this signal as bold and expand it, * as there is at least one signal with handler */ gtk_tree_store_set (editor->model, &parent_class, COLUMN_BOLD, TRUE, -1); - path_parent_class = gtk_tree_model_get_path (GTK_TREE_MODEL (editor->model), &parent_class); - gtk_tree_view_expand_row (GTK_TREE_VIEW (editor->signals_list), path_parent_class, FALSE); + path_parent_class = + gtk_tree_model_get_path (GTK_TREE_MODEL (editor->model), + &parent_class); + gtk_tree_view_expand_row (GTK_TREE_VIEW (editor->signals_list), + path_parent_class, FALSE); gtk_tree_path_free (path_parent_class); - gtk_tree_store_set (editor->model, &parent_signal, - COLUMN_SIGNAL, signal->name, - COLUMN_HANDLER, widget_signal->handler, - COLUMN_AFTER, widget_signal->after, - COLUMN_AFTER_VISIBLE, TRUE, - COLUMN_HANDLER_EDITABLE, TRUE, - COLUMN_SLOT, FALSE, - COLUMN_BOLD, TRUE, -1); + gtk_tree_store_set + (editor->model, &parent_signal, + COLUMN_SIGNAL, signal->name, + COLUMN_HANDLER, widget_signal->handler, + COLUMN_AFTER, widget_signal->after, + COLUMN_USERDATA, + widget_signal->userdata ? + widget_signal->userdata : _(USERDATA_DEFAULT), + COLUMN_LOOKUP, widget_signal->lookup, + COLUMN_LOOKUP_VISIBLE, + widget_signal->userdata ? TRUE : FALSE, + COLUMN_AFTER_VISIBLE, TRUE, + COLUMN_HANDLER_EDITABLE, TRUE, + COLUMN_USERDATA_EDITABLE, TRUE, + COLUMN_SLOT, FALSE, + COLUMN_USERDATA_SLOT, + widget_signal->userdata ? FALSE : TRUE, + COLUMN_BOLD, TRUE, -1); + for (i = 1; i < signals->len; i++) { widget_signal = (GladeSignal*) g_ptr_array_index (signals, i); gtk_tree_store_append (editor->model, &iter, &parent_signal); - gtk_tree_store_set (editor->model, &iter, - COLUMN_HANDLER, widget_signal->handler, - COLUMN_AFTER, widget_signal->after, - COLUMN_AFTER_VISIBLE, TRUE, - COLUMN_HANDLER_EDITABLE, TRUE, - COLUMN_SLOT, FALSE, -1); + + gtk_tree_store_set + (editor->model, &iter, + COLUMN_HANDLER, widget_signal->handler, + COLUMN_AFTER, widget_signal->after, + COLUMN_USERDATA, + widget_signal->userdata ? + widget_signal->userdata : _(USERDATA_DEFAULT), + COLUMN_LOOKUP, widget_signal->lookup, + COLUMN_LOOKUP_VISIBLE, + widget_signal->userdata ? TRUE : FALSE, + COLUMN_AFTER_VISIBLE, TRUE, + COLUMN_HANDLER_EDITABLE, TRUE, + COLUMN_USERDATA_EDITABLE, TRUE, + COLUMN_SLOT, FALSE, + COLUMN_USERDATA_SLOT, + widget_signal->userdata ? FALSE : TRUE, + -1); } /* add the <Type...> slot */ gtk_tree_store_append (editor->model, &iter, &parent_signal); - gtk_tree_store_set (editor->model, &iter, - COLUMN_HANDLER, _("<Type the signal's handler here>"), - COLUMN_AFTER, FALSE, - COLUMN_AFTER_VISIBLE, FALSE, - COLUMN_HANDLER_EDITABLE, TRUE, - COLUMN_SLOT, TRUE, -1); + gtk_tree_store_set + (editor->model, &iter, + COLUMN_HANDLER, _(HANDLER_DEFAULT), + COLUMN_AFTER, FALSE, + COLUMN_USERDATA, _(USERDATA_DEFAULT), + COLUMN_LOOKUP, FALSE, + COLUMN_LOOKUP_VISIBLE, FALSE, + COLUMN_HANDLER_EDITABLE, TRUE, + COLUMN_USERDATA_EDITABLE,FALSE, + COLUMN_AFTER_VISIBLE, FALSE, + COLUMN_SLOT, TRUE, + COLUMN_USERDATA_SLOT, TRUE, -1); } } diff --git a/src/glade-signal.c b/src/glade-signal.c index a6a842ea..60bedeb4 100644 --- a/src/glade-signal.c +++ b/src/glade-signal.c @@ -38,14 +38,19 @@ * * Returns: the new #GladeSignal */ -GladeSignal * -glade_signal_new (const gchar *name, const gchar *handler, gboolean after) +GladeSignal *glade_signal_new (const gchar *name, + const gchar *handler, + const gchar *userdata, + gboolean lookup, + gboolean after) { GladeSignal *signal = g_new0 (GladeSignal, 1); - signal->name = g_strdup (name); - signal->handler = g_strdup (handler); - signal->after = after; + signal->name = g_strdup (name); + signal->handler = g_strdup (handler); + signal->userdata = userdata ? g_strdup (userdata) : NULL; + signal->lookup = lookup; + signal->after = after; return signal; } @@ -63,6 +68,7 @@ glade_signal_free (GladeSignal *signal) g_free (signal->name); g_free (signal->handler); + if (signal->userdata) g_free (signal->userdata); g_free (signal); } @@ -77,15 +83,19 @@ gboolean glade_signal_equal (GladeSignal *sig1, GladeSignal *sig2) { gboolean ret = FALSE; - g_return_val_if_fail (GLADE_IS_SIGNAL (sig1), FALSE); g_return_val_if_fail (GLADE_IS_SIGNAL (sig2), FALSE); - - if (!strcmp (sig1->name, sig2->name) && - !strcmp (sig1->handler, sig2->handler) && - sig1->after == sig2->after) + + if (!strcmp (sig1->name, sig2->name) && + !strcmp (sig1->handler, sig2->handler) && + sig1->after == sig2->after && + sig1->lookup == sig2->lookup) + { + if ((sig1->userdata == NULL && sig2->userdata == NULL) || + (sig1->userdata != NULL && sig2->userdata != NULL && + !strcmp (sig1->userdata, sig2->userdata))) ret = TRUE; - + } return ret; } @@ -98,7 +108,11 @@ glade_signal_equal (GladeSignal *sig1, GladeSignal *sig2) GladeSignal * glade_signal_clone (const GladeSignal *signal) { - return glade_signal_new (signal->name, signal->handler, signal->after); + return glade_signal_new (signal->name, + signal->handler, + signal->userdata, + signal->lookup, + signal->after); } /** @@ -113,10 +127,13 @@ gboolean glade_signal_write (GladeSignalInfo *info, GladeSignal *signal, GladeInterface *interface) { - info->name = alloc_string(interface, signal->name); - info->handler = alloc_string(interface, signal->name); - info->after = signal->after; - + info->name = alloc_string(interface, signal->name); + info->handler = alloc_string(interface, signal->handler); + info->object = + signal->userdata ? + alloc_string(interface, signal->userdata) : NULL; + info->after = signal->after; + info->lookup = signal->lookup; return TRUE; } diff --git a/src/glade-signal.h b/src/glade-signal.h index 30f57a57..64f7033e 100644 --- a/src/glade-signal.h +++ b/src/glade-signal.h @@ -10,15 +10,21 @@ G_BEGIN_DECLS struct _GladeSignal { - gchar *name; /* Signal name eg "clicked" */ - gchar *handler; /* Handler function eg "gtk_main_quit" */ - gboolean after; /* Connect after TRUE or FALSE */ + gchar *name; /* Signal name eg "clicked" */ + gchar *handler; /* Handler function eg "gtk_main_quit" */ + gchar *userdata; /* User data signal handler argument */ + gboolean lookup; /* Whether user_data should be looked up + * with the GModule interface by libglade. + */ + gboolean after; /* Connect after TRUE or FALSE */ }; GladeSignal *glade_signal_new (const gchar *name, const gchar *handler, - gboolean after); + const gchar *userdata, + gboolean lookup, + gboolean after); GladeSignal *glade_signal_clone (const GladeSignal *signal); void glade_signal_free (GladeSignal *signal); diff --git a/src/glade-utils.c b/src/glade-utils.c index f332044d..f7fba621 100644 --- a/src/glade-utils.c +++ b/src/glade-utils.c @@ -27,6 +27,7 @@ #include <gmodule.h> #include "glade.h" #include "glade-project.h" +#include "glade-project-window.h" #include "glade-command.h" #include "glade-debug.h" #include "glade-placeholder.h" @@ -34,6 +35,7 @@ #include "glade-widget-class.h" #include "glade-property.h" #include "glade-property-class.h" +#include "glade-clipboard.h" #define GLADE_UTIL_HAS_NODES "glade_util_has_nodes" #define GLADE_UTIL_SELECTION_NODE_SIZE 7 @@ -712,13 +714,19 @@ glade_util_draw_nodes_idle (GdkWindow *expose_win) /* Step through all the selected widgets in the project. */ for (elem = expose_gwidget->project->selection; elem; elem = elem->next) { + GtkWidget *sel_widget; GdkWindow *sel_win, *sel_toplevel; gint sel_x, sel_y, x, y, w, h; sel_widget = elem->data; - sel_win = glade_util_get_window_positioned_in (sel_widget); - + + if (!GTK_IS_WIDGET (sel_widget)) + continue; + + if ((sel_win = glade_util_get_window_positioned_in (sel_widget)) == NULL) + continue; + /* Calculate the offset of the selected widget's window within its toplevel. */ glade_util_calculate_window_offset (sel_win, &sel_x, &sel_y, @@ -776,7 +784,7 @@ glade_util_queue_draw_nodes (GdkWindow *window) /** - * glade_util_add_nodes: + * glade_util_add_selection: * @widget: a #GtkWidget * * TODO: write me @@ -791,7 +799,7 @@ glade_util_add_selection (GObject *object) } /** - * glade_util_remove_nodes: + * glade_util_remove_selection: * @widget: a #GtkWidget * * TODO: write me @@ -810,7 +818,7 @@ glade_util_remove_selection (GObject *object) } /** - * glade_util_has_nodes: + * glade_util_has_selectoin: * @widget: a #GtkWidget * * Returns: %TRUE if @widget has nodes, %FALSE otherwise @@ -962,29 +970,45 @@ glade_util_uri_list_parse (const gchar *uri_list) } /** - * glade_util_object_set_property: - * @object: a #GObject - * @property: a #GladeProperty + * glade_util_gtkcontainer_relation: + * @widget: a GladeWidget + * @parent: a GladeWidget * - * TODO: write me + * + * Returns whether this widget is parented by a GtkContainer + * and that it is parented through the GtkContainer interface. */ -void -glade_util_object_set_property (GObject *object, GladeProperty *property) +gboolean +glade_util_gtkcontainer_relation (GladeWidget *parent, GladeWidget *widget) { - GValue void_string = {0,}; - GValue *value = property->value; - - if (G_VALUE_HOLDS_STRING (property->value) && - g_value_get_string (property->value) == NULL) - { - g_value_init (&void_string, G_TYPE_STRING); - g_value_set_static_string (&void_string, ""); - value = &void_string; - } - - if (property->class->set_function) - property->class->set_function (object, value); - else - g_object_set_property (object, property->class->id, value); + GladeSupportedChild *support; + return (GTK_IS_CONTAINER (parent->object) && + (support = glade_widget_class_get_child_support + (parent->widget_class, widget->widget_class->type)) && + (support->type == GTK_TYPE_WIDGET)); } +/** + * glade_util_gtkcontainer_relation: + * @widget: a GladeWidget + * + * Returns whether this widget has an implementation to parent + * the primary selection on the clipboard. + */ +gboolean +glade_util_widget_pastable (GladeWidget *parent) +{ + GladeProjectWindow *gpw; + GladeClipboard *clipboard; + GladeWidget *clip_widget; + + gpw = glade_project_window_get (); + clipboard = gpw->clipboard; + clip_widget = clipboard->curr; + + if (clip_widget) + return (glade_widget_class_get_child_support + (parent->widget_class, + clip_widget->widget_class->type) != NULL) ? TRUE : FALSE; + return FALSE; +} diff --git a/src/glade-utils.h b/src/glade-utils.h index 7806d5c5..532dbfdb 100644 --- a/src/glade-utils.h +++ b/src/glade-utils.h @@ -26,18 +26,20 @@ void glade_util_flash_message (GtkWidget *statusbar, /* This is a GCompareFunc for comparing the labels of 2 stock items, ignoring any '_' characters. It isn't particularly efficient. */ -gint glade_util_compare_stock_labels (gconstpointer a, gconstpointer b); +gint glade_util_compare_stock_labels (gconstpointer a, gconstpointer b); -void glade_util_hide_window (GtkWindow *window); -gchar *glade_util_gtk_combo_func (gpointer data); +void glade_util_hide_window (GtkWindow *window); +gchar *glade_util_gtk_combo_func (gpointer data); gpointer glade_util_gtk_combo_find (GtkCombo *combo); -GtkWidget *glade_util_file_dialog_new (const gchar *title, GtkWindow *parent, GladeUtilFileDialogType action); -gchar *glade_util_file_dialog_get_filename (GtkWidget *file_dialog); -void glade_util_file_dialog_set_filename (GtkWidget *file_dialog, gchar *filename); +GtkWidget *glade_util_file_dialog_new (const gchar *title, + GtkWindow *parent, + GladeUtilFileDialogType action); +gchar *glade_util_file_dialog_get_filename (GtkWidget *file_dialog); +void glade_util_file_dialog_set_filename (GtkWidget *file_dialog, gchar *filename); -void glade_util_replace (char *str, char a, char b); -char *glade_util_duplicate_underscores (const char *name); +void glade_util_replace (char *str, char a, char b); +gchar *glade_util_duplicate_underscores (const char *name); void glade_util_delete_selection (GladeProject *project); @@ -46,12 +48,13 @@ 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); -GList *glade_util_container_get_all_children (GtkContainer *container); -void glade_util_object_set_property (GObject *object, GladeProperty *property); +GladeWidget *glade_util_get_parent (GtkWidget *w); +GList *glade_util_container_get_all_children (GtkContainer *container); -GList *glade_util_uri_list_parse (const gchar* uri_list); +GList *glade_util_uri_list_parse (const gchar* uri_list); +gboolean glade_util_gtkcontainer_relation (GladeWidget *parent, GladeWidget *widget); +gboolean glade_util_widget_pastable (GladeWidget *parent); G_END_DECLS diff --git a/src/glade-widget-class.c b/src/glade-widget-class.c index 20cdb474..7fd6293f 100644 --- a/src/glade-widget-class.c +++ b/src/glade-widget-class.c @@ -244,7 +244,7 @@ glade_widget_class_list_signals (GladeWidgetClass *class) g_return_val_if_fail (class->type != 0, NULL); type = class->type; - while (g_type_is_a (type, GTK_TYPE_OBJECT)) + while (g_type_is_a (type, G_TYPE_OBJECT)) { if (G_TYPE_IS_INSTANTIATABLE (type) || G_TYPE_IS_INTERFACE (type)) { @@ -286,10 +286,9 @@ glade_widget_class_create_icon (GladeWidgetClass *class) static void glade_widget_class_update_properties_from_node (GladeXmlNode *node, GladeWidgetClass *widget_class, - GList **pproperties) + GList **properties) { GladeXmlNode *child; - GList *properties = *pproperties; for (child = glade_xml_node_get_children (node); child; child = glade_xml_node_next (child)) @@ -308,12 +307,14 @@ glade_widget_class_update_properties_from_node (GladeXmlNode *node, continue; /* find the property in our list, if not found append a new property */ - for (list = properties; list; list = list->next) + for (list = *properties; list && list->data; list = list->next) { - gchar *tmp = GLADE_PROPERTY_CLASS (list->data)->id; - if (!g_ascii_strcasecmp (id, tmp)) + property_class = GLADE_PROPERTY_CLASS (list->data); + if (property_class->id != NULL && + g_ascii_strcasecmp (id, property_class->id) == 0) break; } + if (list) { property_class = GLADE_PROPERTY_CLASS (list->data); @@ -322,8 +323,8 @@ glade_widget_class_update_properties_from_node (GladeXmlNode *node, { property_class = glade_property_class_new (); property_class->id = g_strdup (id); - properties = g_list_append (properties, property_class); - list = g_list_last (properties); + *properties = g_list_append (*properties, property_class); + list = g_list_last (*properties); } updated = glade_property_class_update_from_node @@ -338,7 +339,7 @@ glade_widget_class_update_properties_from_node (GladeXmlNode *node, /* the property has Disabled=TRUE ... */ if (!property_class) - properties = g_list_delete_link (properties, list); + *properties = g_list_delete_link (*properties, list); g_free (id); } @@ -407,7 +408,7 @@ glade_widget_class_update_children_from_node (GladeXmlNode *node, } else { - child = g_new (GladeSupportedChild, 1); + child = g_new0 (GladeSupportedChild, 1); child->type = type; widget_class->children = g_list_append (widget_class->children, child); } @@ -537,6 +538,61 @@ glade_widget_class_get_by_name (const char *name) return NULL; } +typedef struct +{ + GType type; + GladeWidgetClass *class; +} GladeClassSearchPair; + +static void +search_class_by_type (gchar *name, + GladeWidgetClass *class, + GladeClassSearchPair *pair) +{ + if (class->type == pair->type) + pair->class = class; +} + +GladeWidgetClass * +glade_widget_class_get_by_type (GType type) +{ + GladeClassSearchPair pair = { type, NULL }; + + if (widget_classes != NULL) + { + g_hash_table_foreach (widget_classes, (GHFunc)search_class_by_type, &pair); + } + return pair.class; +} + +typedef struct +{ + GType type; + GList *list; +} GladeClassAccumPair; + +static void +accum_class_by_type (gchar *name, + GladeWidgetClass *class, + GladeClassAccumPair *pair) +{ + if (g_type_is_a (class->type, pair->type)) + pair->list = g_list_prepend (pair->list, class); +} + +GList * +glade_widget_class_get_derived_types (GType type) +{ + GladeClassAccumPair pair = { type, NULL }; + + if (widget_classes != NULL) + { + g_hash_table_foreach (widget_classes, (GHFunc)accum_class_by_type, &pair); + } + return pair.list; +} + + /** * glade_widget_class_merge_properties: * @widget_properties: Pointer to the list of properties in the widget. @@ -832,7 +888,7 @@ glade_widget_class_new (const char *name, widget_class->generic_name = generic_name ? g_strdup (generic_name) : NULL; widget_class->palette_name = palette_name ? g_strdup (palette_name) : NULL; widget_class->name = g_strdup (name); - widget_class->in_palette = generic_name ? TRUE : FALSE; + widget_class->in_palette = palette_name ? TRUE : FALSE; widget_class->type = glade_util_get_type_from_name (widget_class->name); if (widget_class->type == 0) diff --git a/src/glade-widget-class.h b/src/glade-widget-class.h index 3ca1cdb3..38d0c7f6 100644 --- a/src/glade-widget-class.h +++ b/src/glade-widget-class.h @@ -148,6 +148,8 @@ GladeWidgetClass *glade_widget_class_new (const char *na 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); +GladeWidgetClass *glade_widget_class_get_by_type (GType type); +GList *glade_widget_class_get_derived_types (GType type); 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, diff --git a/src/glade-widget.c b/src/glade-widget.c index 17bb33fd..63c59a88 100644 --- a/src/glade-widget.c +++ b/src/glade-widget.c @@ -81,7 +81,8 @@ enum PROP_OBJECT, PROP_CLASS, PROP_PROJECT, - PROP_PROPERTIES + PROP_PROPERTIES, + PROP_PARENT }; static guint glade_widget_signals[LAST_SIGNAL] = {0}; @@ -184,8 +185,12 @@ glade_widget_class_init (GladeWidgetKlass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_pointer ("parent", _("Parent"), + _("A pointer to the parenting GladeWidget"), + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); glade_widget_signals[ADD_SIGNAL_HANDLER] = g_signal_new ("add_signal_handler", @@ -316,32 +321,24 @@ glade_widget_copy_packing_props (GladeWidget *parent, } static void -glade_widget_copy_custom_props (GladeWidget *widget, - GladeWidget *template) +glade_widget_sync_custom_props (GladeWidget *widget) { GList *l; for (l = widget->properties; l && l->data; l = l->next) { - GladeProperty *dup_prop = GLADE_PROPERTY(l->data); - GladeProperty *orig_prop; - if (dup_prop->class->set_function) - { - orig_prop = glade_widget_get_property (template, dup_prop->class->id); - - glade_property_set (dup_prop, orig_prop->value); - } + GladeProperty *prop = GLADE_PROPERTY(l->data); + if (prop->class->set_function) + glade_property_sync (prop); } } static void -glade_widget_sync_custom_props (GladeWidget *widget) +glade_widget_sync_packing_props (GladeWidget *widget) { GList *l; - for (l = widget->properties; l && l->data; l = l->next) - { + for (l = widget->packing_properties; l && l->data; l = l->next) { GladeProperty *prop = GLADE_PROPERTY(l->data); - if (prop->class->set_function) - glade_property_sync (prop); + glade_property_sync (prop); } } @@ -493,38 +490,28 @@ glade_widget_build_object (GladeWidgetClass *klass, GladeWidget *widget) } static GladeWidget * -glade_widget_internal_new (GladeWidgetClass *klass, GladeProject *project, GladeWidget *template) +glade_widget_internal_new (const gchar *name, + GladeWidget *parent, + GladeWidgetClass *klass, + GladeProject *project, + GladeWidget *template) { GObject *object; GObject *glade_widget; - GList *properties; - gchar *widget_name; + GList *properties = NULL; - object = glade_widget_build_object(klass, template); - widget_name = glade_project_new_widget_name (project, klass->generic_name); - + object = glade_widget_build_object(klass, template); 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); + glade_widget = g_object_new (GLADE_TYPE_WIDGET, + "parent", parent, + "properties", properties, + "class", klass, + "project", project, + "name", name, + "object", object, + NULL); return (GladeWidget *) glade_widget; } @@ -539,11 +526,15 @@ glade_widget_internal_new (GladeWidgetClass *klass, GladeProject *project, Glade * Returns: */ GladeWidget * -glade_widget_new (GladeWidgetClass *klass, GladeProject *project) +glade_widget_new (GladeWidget *parent, GladeWidgetClass *klass, GladeProject *project) { GladeWidget *widget; - - if ((widget = glade_widget_internal_new (klass, project, NULL)) != NULL) + gchar *widget_name = + glade_project_new_widget_name + (project, klass->generic_name); + + if ((widget = glade_widget_internal_new + (widget_name, parent, klass, project, NULL)) != NULL) { glade_widget_class_container_fill_empty (klass, widget->object); @@ -558,6 +549,7 @@ glade_widget_new (GladeWidgetClass *klass, GladeProject *project) */ glade_widget_sync_custom_props (widget); } + g_free (widget_name); return widget; } @@ -570,13 +562,15 @@ glade_widget_new (GladeWidgetClass *klass, GladeProject *project) * Returns: */ static GladeWidget * -glade_widget_dup_internal (GladeWidget *template) +glade_widget_dup_internal (GladeWidget *parent, GladeWidget *template) { GladeWidget *gwidget; GList *list, *children; g_return_val_if_fail (template != NULL && GLADE_IS_WIDGET(template), NULL); - gwidget = glade_widget_internal_new (template->widget_class, + gwidget = glade_widget_internal_new (glade_widget_get_name(template), + parent, + template->widget_class, template->project, template); @@ -594,9 +588,7 @@ glade_widget_dup_internal (GladeWidget *template) if (child_gwidget->internal == NULL) { - child_dup = glade_widget_dup_internal (child_gwidget); - - child_dup->parent = gwidget; + child_dup = glade_widget_dup_internal (gwidget, child_gwidget); glade_widget_class_container_add (gwidget->widget_class, gwidget->object, @@ -630,8 +622,8 @@ glade_widget_dup_internal (GladeWidget *template) } g_list_free (children); } - - glade_widget_copy_custom_props (gwidget, template); + + glade_widget_sync_custom_props (gwidget); if (GTK_IS_WIDGET (gwidget->object) && !GTK_WIDGET_TOPLEVEL(gwidget->object)) gtk_widget_show_all (GTK_WIDGET (gwidget->object)); @@ -642,7 +634,7 @@ glade_widget_dup_internal (GladeWidget *template) GladeWidget * glade_widget_dup (GladeWidget *template) { - GladeWidget *widget = glade_widget_dup_internal (template); + GladeWidget *widget = glade_widget_dup_internal (NULL, template); if (widget) glade_widget_fill_all_empty (widget); return widget; @@ -677,7 +669,11 @@ glade_widget_rebuild (GladeWidget *glade_widget) /* Custom properties aren't transfered in build_object, since build_object * is only concerned with object creation. */ - glade_widget_sync_custom_props (glade_widget); + glade_widget_sync_custom_props (glade_widget); + + /* Sync packing. + */ + glade_widget_sync_packing_props (glade_widget); if (g_type_is_a (klass->type, GTK_TYPE_WIDGET)) { @@ -712,16 +708,13 @@ glade_widget_new_for_internal_child (GladeWidgetClass *klass, GladeProject *project = glade_widget_get_project (parent); gchar *widget_name = glade_project_new_widget_name (project, klass->generic_name); GladeWidget *widget = g_object_new (GLADE_TYPE_WIDGET, + "parent", parent, "class", klass, "project", project, "name", widget_name, "internal", internal_name, "object", internal_object, NULL); g_free (widget_name); - - widget->parent = parent; - - glade_widget_set_packing_properties (widget, parent); return widget; } @@ -857,6 +850,9 @@ glade_widget_set_real_property (GObject *object, case PROP_PROPERTIES: glade_widget_set_properties (widget, (GList *)g_value_get_pointer (value)); break; + case PROP_PARENT: + glade_widget_set_parent (widget, GLADE_WIDGET (g_value_get_pointer (value))); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -892,6 +888,10 @@ glade_widget_get_real_property (GObject *object, break; case PROP_PROPERTIES: g_value_set_pointer (value, widget->properties); + break; + case PROP_PARENT: + g_value_set_pointer (value, widget->parent); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -910,7 +910,8 @@ glade_widget_set_name (GladeWidget *widget, const gchar *name) { g_return_if_fail (GLADE_IS_WIDGET (widget)); if (widget->name != name) { - g_free (widget->name); + if (widget->name) + g_free (widget->name); widget->name = g_strdup (name); g_object_notify (G_OBJECT (widget), "name"); } @@ -1005,8 +1006,8 @@ glade_widget_set_class (GladeWidget *widget, GladeWidgetClass *klass) 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); + g_warning ("Failed to create [%s] property", + property_class->id); continue; } @@ -1106,7 +1107,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_gobject (widget); - glade_popup_widget_pop (glade_widget, NULL); + glade_popup_widget_pop (glade_widget, NULL, TRUE); return TRUE; } @@ -1212,7 +1213,9 @@ glade_widget_button_press (GtkWidget *widget, { /* if it's already selected don't stop default handlers, e.g. toggle button */ if (glade_util_has_selection (G_OBJECT(widget))) + { return FALSE; + } glade_project_selection_set (glade_widget->project, G_OBJECT(widget), TRUE); @@ -1220,7 +1223,7 @@ glade_widget_button_press (GtkWidget *widget, } else if (event->button == 3) { - glade_popup_widget_pop (glade_widget, event); + glade_popup_widget_pop (glade_widget, event, TRUE); return TRUE; } @@ -1326,8 +1329,8 @@ glade_widget_transport_children (GladeWidget *gwidget, { for (list = children; list && list->data; list = list->next) { - GObject *child = G_OBJECT(list->data); - + GObject *child = G_OBJECT(list->data); + GladeWidget *gchild = glade_widget_get_from_gobject (child); /* 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. @@ -1337,8 +1340,8 @@ glade_widget_transport_children (GladeWidget *gwidget, 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); + glade_widget_sync_packing_props (gchild); + g_object_unref(child); } g_list_free (children); @@ -1346,35 +1349,6 @@ glade_widget_transport_children (GladeWidget *gwidget, } /** - * glade_widget_update_parent: - * @widget: A #GladeWidget - * @old_object: A #GObject - * @new_object: A #GObject - * - * Finds @widget's parent #GladeWidget and calls the replace_child func - * and takes care of packing - * - * Returns: whether this widget had a parent. - */ -static gboolean -glade_widget_update_parent(GladeWidget *parent, GObject *old_object, GObject *new_object) -{ - if (old_object) - { - 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); - - return TRUE; - } - return FALSE; -} - -/** * glade_widget_set_object: * @gwidget: * @new_widget: @@ -1385,7 +1359,6 @@ void glade_widget_set_object (GladeWidget *gwidget, GObject *new_object) { GladeWidgetClass *klass; - GladeWidget *parent; GObject *old_object; g_return_if_fail (GLADE_IS_WIDGET (gwidget)); @@ -1428,13 +1401,21 @@ glade_widget_set_object (GladeWidget *gwidget, GObject *new_object) 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); - + /* Take care of hierarchy here + */ + if (old_object) + { + if (gwidget->parent) + { + glade_widget_class_container_replace_child + (gwidget->parent->widget_class, + gwidget->parent->object, + old_object, new_object); + } + glade_widget_transport_children (gwidget, old_object, new_object); + } } - if (old_object) - glade_widget_transport_children (gwidget, old_object, new_object); /* Remove internal reference to old widget */ if (old_object) { @@ -1512,7 +1493,7 @@ glade_widget_real_change_signal_handler (GladeWidget *widget, GPtrArray *signals; GladeSignal *tmp_signal_handler; gint i; - + g_return_if_fail (GLADE_IS_WIDGET (widget)); g_return_if_fail (GLADE_IS_SIGNAL (old_signal_handler)); g_return_if_fail (GLADE_IS_SIGNAL (new_signal_handler)); @@ -1535,7 +1516,21 @@ glade_widget_real_change_signal_handler (GladeWidget *widget, tmp_signal_handler->handler = g_strdup (new_signal_handler->handler); } - tmp_signal_handler->after = new_signal_handler->after; + + /* Handler */ + if (tmp_signal_handler->handler) + g_free (tmp_signal_handler->handler); + tmp_signal_handler->handler = + g_strdup (new_signal_handler->handler); + + /* Object */ + if (tmp_signal_handler->userdata) + g_free (tmp_signal_handler->userdata); + tmp_signal_handler->userdata = + g_strdup (new_signal_handler->userdata); + + tmp_signal_handler->after = new_signal_handler->after; + tmp_signal_handler->lookup = new_signal_handler->lookup; break; } } @@ -1555,6 +1550,23 @@ glade_widget_get_parent (GladeWidget *widget) return widget->parent; } +void +glade_widget_set_parent (GladeWidget *widget, + GladeWidget *parent) +{ + GladeWidget *old_parent = widget->parent; + widget->parent = parent; + + if (widget->object && + (old_parent == NULL || widget->packing_properties == NULL || + old_parent->widget_class->type != parent->widget_class->type)) + glade_widget_set_packing_properties (widget, parent); + else + glade_widget_sync_packing_props (widget); + + g_object_notify (G_OBJECT (widget), "parent"); +} + /** * Returns a list of GladeProperties from a list for the correct * child type for this widget of this container. @@ -1578,7 +1590,7 @@ glade_widget_create_packing_properties (GladeWidget *container, GladeWidget *wid packing_props = g_list_prepend (packing_props, property); } } - return packing_props; + return g_list_reverse (packing_props); } /** @@ -1643,16 +1655,26 @@ glade_widget_replace (GladeWidget *parent, GObject *old_object, GObject *new_obj gnew_widget = glade_widget_get_from_gobject (new_object); gold_widget = glade_widget_get_from_gobject (old_object); - if (gnew_widget) { + if (gnew_widget) + { real_new_object = glade_widget_get_object (gnew_widget); gnew_widget->parent = parent; } - if (gold_widget) { + + if (gold_widget) + { real_old_object = glade_widget_get_object (gold_widget); gold_widget->parent = NULL; } - glade_widget_update_parent(parent, real_old_object, real_new_object); + glade_widget_class_container_replace_child (parent->widget_class, + parent->object, + real_old_object, + real_new_object); + + if (gnew_widget) + glade_widget_set_packing_properties (gnew_widget, parent); + } /* XML Serialization */ @@ -1680,7 +1702,7 @@ glade_widget_write_signals (gpointer key, gpointer value, gpointer user_data) GladeSignalInfo signalinfo; glade_signal_write (&signalinfo, signal, - write_signals_context->interface); + write_signals_context->interface); g_array_append_val (write_signals_context->signals, signalinfo); } @@ -1824,7 +1846,7 @@ glade_widget_value_from_prop_info (GladePropInfo *info, 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, @@ -1887,7 +1909,6 @@ glade_widget_fill_from_widget_info (GladeWidgetInfo *info, g_return_if_fail (info != NULL); g_assert (strcmp (info->classname, widget->widget_class->name) == 0); - glade_widget_set_name (widget, info->name); /* Children */ for (i = 0; i < info->n_children; ++i) @@ -1983,10 +2004,11 @@ glade_widget_properties_from_widget_info (GladeWidgetClass *class, /* 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 + 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); + property = glade_property_new (pclass, NULL, value); + property->enabled = value ? TRUE : property->enabled; + properties = g_list_prepend (properties, property); } return g_list_reverse (properties); } @@ -2069,7 +2091,6 @@ glade_widget_new_from_widget_info (GladeWidgetInfo *info, GladeWidgetClass *klass; GladeWidget *widget; GObject *object; - gchar *widget_name; GArray *params; GList *properties; @@ -2091,23 +2112,25 @@ glade_widget_new_from_widget_info (GladeWidgetInfo *info, glade_widget_params_free (params); - - widget_name = glade_project_new_widget_name (project, klass->generic_name); widget = g_object_new (GLADE_TYPE_WIDGET, + "parent", parent, "properties", properties, - "class", klass, - "project", project, - "name", widget_name, - "object", object, NULL); - g_free (widget_name); + "class", klass, + "project", project, + "name", info->name, + "object", object, NULL); /* create the packing_properties list, without setting them */ if (parent) widget->packing_properties = glade_widget_create_packing_properties (parent, widget); + /* Load children first */ glade_widget_fill_from_widget_info (info, widget, FALSE); + /* Now sync custom props, things like "size" on GtkBox need + * this to be done afterwards. + */ glade_widget_sync_custom_props (widget); glade_widget_class_container_fill_empty (klass, object); @@ -2190,6 +2213,8 @@ glade_widget_new_child_from_child_info (GladeChildInfo *info, child->parent = parent; glade_widget_class_container_add (parent->widget_class, parent->object, child->object); + + glade_widget_sync_packing_props (child); } /* Get the packing properties */ @@ -2216,9 +2241,13 @@ glade_widget_new_child_from_child_info (GladeChildInfo *info, GladeWidget * glade_widget_read (GladeProject *project, GladeWidgetInfo *info) { - GladeWidget *widget = - glade_widget_new_from_widget_info (info, project, NULL); - if (verbose) - glade_widget_debug (widget); + GladeWidget *widget; + + if ((widget = glade_widget_new_from_widget_info + (info, project, NULL)) != NULL) + { + if (verbose) + glade_widget_debug (widget); + } return widget; } diff --git a/src/glade-widget.h b/src/glade-widget.h index 06688665..3cfe64da 100644 --- a/src/glade-widget.h +++ b/src/glade-widget.h @@ -81,7 +81,8 @@ struct _GladeWidgetKlass }; GType glade_widget_get_type (void); -GladeWidget * glade_widget_new (GladeWidgetClass *klass, +GladeWidget * glade_widget_new (GladeWidget *widget, + GladeWidgetClass *klass, GladeProject *project); GladeWidget * glade_widget_new_for_internal_child (GladeWidgetClass *klass, GladeWidget *parent, @@ -134,6 +135,8 @@ GladeWidget *glade_widget_read (GladeProject *p g_object_get_data (G_OBJECT (w), "GladeWidgetDataTag") GladeWidget *glade_widget_get_parent (GladeWidget *widget); +void glade_widget_set_parent (GladeWidget *widget, + GladeWidget *parent); G_END_DECLS |