diff options
author | Juan Pablo Ugarte <jpu@src.gnome.org> | 2006-07-13 21:38:19 +0000 |
---|---|---|
committer | Juan Pablo Ugarte <jpu@src.gnome.org> | 2006-07-13 21:38:19 +0000 |
commit | 0c4e3578b1c9f6a38e14968d1fc6f3bef23daa14 (patch) | |
tree | f8093d642c0a3981e326080ad8f63a3c5e79fffb | |
parent | 8ce781c124bd8364fbf0640324cc4254dadf4cb9 (diff) | |
download | glade-0c4e3578b1c9f6a38e14968d1fc6f3bef23daa14.tar.gz |
added files glade-base-editor.[ch]
* src/Makefile.am: added files glade-base-editor.[ch]
* src/glade-accumulators.[ch]: new accumulators
glade_string_accumulator() and glade_stop_emission_accumulator ()
* src/glade-app.c, src/glade-project.c and src/glade-command.c:
use of GladeWidgetClass toplevel flag.
* src/glade-gtk.c: Use of GladeBaseEditor for GtkMenuBar, GtkToolBar
and GtkMenu editors.
* src/glade-marshallers.list: added OBJECT:OBJECT,UINT
BOOLEAN:OBJECT,UINT BOOLEAN:OBJECT,OBJECT and STRING:OBJECT
* src/glade-property.[ch]: Added old_value parameter to GladeProject
"value_changed" signal.
* src/glade-widget-class.[ch]: added toplevel flag to GladeWidgetClass
* src/glade.h: added GLADE_XML_TAG_TOPLEVEL
* src/glade-base-editor.[ch]: Created GladeBaseEditor class from
GtkMenuBarEditor code from glade-gtk.c
* widgets/gtk+.xml.in:
o added launch-editor-function for GtkToolbar and GtkMenu.
o Set GtkTextView post-create-function to empty (we do not need a
placeholder in it).
o Set toplevel="True" in GtkWindow and GtkMenu.
* doc/widgetclasses.sgml: added toplevel property docs
* po/POTFILES.in: added src/glade-base-editor.c
-rw-r--r-- | ChangeLog | 36 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | doc/widgetclasses.sgml | 10 | ||||
-rw-r--r-- | po/POTFILES.in | 2 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/glade-accumulators.c | 27 | ||||
-rw-r--r-- | src/glade-accumulators.h | 18 | ||||
-rw-r--r-- | src/glade-app.c | 2 | ||||
-rw-r--r-- | src/glade-base-editor.c | 1876 | ||||
-rw-r--r-- | src/glade-base-editor.h | 100 | ||||
-rw-r--r-- | src/glade-command.c | 2 | ||||
-rw-r--r-- | src/glade-editor-property.c | 1 | ||||
-rw-r--r-- | src/glade-gtk.c | 1726 | ||||
-rw-r--r-- | src/glade-marshallers.list | 4 | ||||
-rw-r--r-- | src/glade-project.c | 2 | ||||
-rw-r--r-- | src/glade-property.c | 13 | ||||
-rw-r--r-- | src/glade-property.h | 2 | ||||
-rw-r--r-- | src/glade-widget-class.c | 8 | ||||
-rw-r--r-- | src/glade-widget-class.h | 4 | ||||
-rw-r--r-- | src/glade.h | 1 | ||||
-rw-r--r-- | widgets/gtk+.xml.in | 9 |
21 files changed, 2454 insertions, 1395 deletions
@@ -1,3 +1,39 @@ +2006-07-13 Juan Pablo Ugarte <juanpablougarte@gmail.com> + + * src/Makefile.am: added files glade-base-editor.[ch] + + * src/glade-accumulators.[ch]: new accumulators + glade_string_accumulator() and glade_stop_emission_accumulator () + + * src/glade-app.c, src/glade-project.c and src/glade-command.c: + use of GladeWidgetClass toplevel flag. + + * src/glade-gtk.c: Use of GladeBaseEditor for GtkMenuBar, GtkToolBar + and GtkMenu editors. + + * src/glade-marshallers.list: added OBJECT:OBJECT,UINT + BOOLEAN:OBJECT,UINT BOOLEAN:OBJECT,OBJECT and STRING:OBJECT + + * src/glade-property.[ch]: Added old_value parameter to GladeProject + "value_changed" signal. + + * src/glade-widget-class.[ch]: added toplevel flag to GladeWidgetClass + + * src/glade.h: added GLADE_XML_TAG_TOPLEVEL + + * src/glade-base-editor.[ch]: Created GladeBaseEditor class from + GtkMenuBarEditor code from glade-gtk.c + + * widgets/gtk+.xml.in: + o added launch-editor-function for GtkToolbar and GtkMenu. + o Set GtkTextView post-create-function to empty (we do not need a + placeholder in it). + o Set toplevel="True" in GtkWindow and GtkMenu. + + * doc/widgetclasses.sgml: added toplevel property docs + + * po/POTFILES.in: added src/glade-base-editor.c + 2006-07-06 Vincent Geddes <vgeddes@metroweb.co.za> * pixmaps/16x16/Makefile.am, pixmaps/22x22/Makefile.am: @@ -2,9 +2,7 @@ Tasks/Bugs Blocking glade-3 3.0: ================================ - o Toolbar editor / Popup menu editor (Juan Pablo: working on it) o Implement GnomeDB widget catalog. (Daniel) o DevHelp gets spawned with version 0.11 (bug 344043) o Default notebook tab labels (bug 345438) (Tristan) o GtkButton saves a previously set label when later set to container mode (bug 346139) - diff --git a/doc/widgetclasses.sgml b/doc/widgetclasses.sgml index 48c4de2d..b923ccc3 100644 --- a/doc/widgetclasses.sgml +++ b/doc/widgetclasses.sgml @@ -86,6 +86,16 @@ tree and will be translated before use in the interface. </varlistentry> <varlistentry> + <term>toplevel</term> + <listitem> + <para> +The'toplevel' property is used to know whether this widget class is toplevel or not +in Glade context. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>post-create-function</term> <listitem> <para> diff --git a/po/POTFILES.in b/po/POTFILES.in index ba45b2ed..4140bd2e 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -9,6 +9,7 @@ src/glade-project-window.c # libgladeui shared core library src/glade-app.c src/glade-builtins.c +src/glade-base-editor.c src/glade-catalog.c src/glade-clipboard-view.c src/glade-clipboard.c @@ -44,4 +45,3 @@ src/glade-gnome.c widgets/gnome.xml.in widgets/bonobo.xml.in widgets/canvas.xml.in - diff --git a/src/Makefile.am b/src/Makefile.am index 98f16699..f6e47754 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -85,7 +85,8 @@ libgladeui_1_la_SOURCES = \ glade-builtins.c \ glade-app.c \ glade-keysyms.c \ - glade-fixed.c + glade-fixed.c \ + glade-base-editor.c libgladeui_1_la_CFLAGS = \ -DINSIDE_LIBGLADEUI \ @@ -133,6 +134,7 @@ libgladeuiinclude_HEADERS = \ glade-app.h \ glade-builtins.h \ glade-fixed.h \ + glade-base-editor.h \ fixed_bg.xpm \ atk.xpm diff --git a/src/glade-accumulators.c b/src/glade-accumulators.c index bcc6e345..2c1143c0 100644 --- a/src/glade-accumulators.c +++ b/src/glade-accumulators.c @@ -53,3 +53,30 @@ glade_boolean_handled_accumulator (GSignalInvocationHint *ihint, return continue_emission; } + +gboolean +glade_string_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy) +{ + const gchar *handler_str; + + g_free ((void *)g_value_get_string (return_accu)); + + handler_str = g_value_get_string (handler_return); + g_value_set_string (return_accu, handler_str); + + return (handler_str == NULL); +} + +gboolean +glade_stop_emission_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy) +{ + g_value_copy (handler_return, return_accu); + + return FALSE; +} diff --git a/src/glade-accumulators.h b/src/glade-accumulators.h index 333149fc..dcea4515 100644 --- a/src/glade-accumulators.h +++ b/src/glade-accumulators.h @@ -6,17 +6,25 @@ G_BEGIN_DECLS -gboolean glade_single_object_accumulator (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer dummy); - +gboolean glade_single_object_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy); + gboolean glade_boolean_handled_accumulator (GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, gpointer dummy); +gboolean glade_string_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy); +gboolean glade_stop_emission_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy); G_END_DECLS #endif /* __GLADE_ACCUM_H__ */ diff --git a/src/glade-app.c b/src/glade-app.c index 2bbafb39..a82e2e38 100644 --- a/src/glade-app.c +++ b/src/glade-app.c @@ -271,7 +271,7 @@ on_palette_button_clicked (GladePalette *palette, GladeApp *app) class = glade_palette_get_current_item_class (palette); /* class may be NULL if the selector was pressed */ - if (class && g_type_is_a (class->type, GTK_TYPE_WINDOW)) + if (class && class->toplevel) { widget = glade_command_create (class, NULL, NULL, app->priv->active_project); diff --git a/src/glade-base-editor.c b/src/glade-base-editor.c new file mode 100644 index 00000000..bc9d1e91 --- /dev/null +++ b/src/glade-base-editor.c @@ -0,0 +1,1876 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2006 Juan Pablo Ugarte. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Authors: + * Juan Pablo Ugarte <juanpablougarte@gmail.com> + */ + +#include "glade.h" +#include "glade-editor-property.h" +#include "glade-base-editor.h" +#include "glade-accumulators.h" + +#include <string.h> +#include <glib/gi18n-lib.h> +#include <gdk/gdkkeysyms.h> + +typedef enum +{ + GLADE_BASE_EDITOR_GTYPE, + GLADE_BASE_EDITOR_NAME, + GLADE_BASE_EDITOR_N_COLUMNS +}GladeBaseEditorChildEnum; + +typedef enum +{ + GLADE_BASE_EDITOR_MENU_GWIDGET, + GLADE_BASE_EDITOR_MENU_OBJECT, + GLADE_BASE_EDITOR_MENU_TYPE_NAME, + GLADE_BASE_EDITOR_MENU_NAME, + GLADE_BASE_EDITOR_MENU_N_COLUMNS +}GladeBaseEditorEnum; + +struct _GladeBaseEditorPrivate +{ + GladeWidget *gcontainer; /* The container we are editing */ + GtkListStore *children; + + /* Editor UI */ + GtkWidget *paned, *popup, *table, *treeview; + GtkWidget *remove_button, *signal_editor_w; + GladeSignalEditor *signal_editor; + + GtkListStore *lstore; + GtkTreeStore *tstore; + GtkTreeModel *model; + GladeProject *project; + + /* Add button data */ + GType add_type; + gboolean add_as_child; + + /* Temporal variables */ + GtkTreeIter iter; /* used in idle functions */ + gint row; + + gboolean updating_treeview; +}; + +typedef struct _GladeBaseEditorSignal GladeBaseEditorSignal; +typedef enum _GladeBaseEditorSignalType GladeBaseEditorSignalType; + +enum _GladeBaseEditorSignalType +{ + SIGNAL_CHILD_SELECTED, + SIGNAL_CHANGE_TYPE, + SIGNAL_GET_DISPLAY_NAME, + SIGNAL_BUILD_CHILD, + SIGNAL_DELETE_CHILD, + SIGNAL_MOVE_CHILD, + LAST_SIGNAL +}; + +struct _GladeBaseEditorSignal +{ + GladeBaseEditor *object; +}; + +static guint glade_base_editor_signals [LAST_SIGNAL] = { 0 }; +static GtkVBoxClass *parent_class = NULL; + +static void glade_base_editor_set_container (GladeBaseEditor *editor, + GObject *container); +static void glade_base_editor_block_callbacks (GladeBaseEditor *editor, + gboolean block); + +/* glade_base_editor_store_* wrapper functions to use the tree/list store */ +static void +glade_base_editor_store_set (GladeBaseEditor *editor, GtkTreeIter *iter, ...) +{ + va_list args; + + va_start (args, iter); + + if (editor->priv->tstore) + gtk_tree_store_set_valist (editor->priv->tstore, iter, args); + else + gtk_list_store_set_valist (editor->priv->lstore, iter, args); + + va_end (args); +} + +static void +glade_base_editor_store_remove (GladeBaseEditor *editor, GtkTreeIter *iter) +{ + if (editor->priv->tstore) + gtk_tree_store_remove (editor->priv->tstore, iter); + else + gtk_list_store_remove (editor->priv->lstore, iter); +} + +static void +glade_base_editor_store_clear (GladeBaseEditor *editor) +{ + gtk_tree_view_set_model (GTK_TREE_VIEW (editor->priv->treeview), NULL); + + if (editor->priv->tstore) + gtk_tree_store_clear (editor->priv->tstore); + else + gtk_list_store_clear (editor->priv->lstore); + + gtk_tree_view_set_model (GTK_TREE_VIEW (editor->priv->treeview), editor->priv->model); +} + +static void +glade_base_editor_store_append (GladeBaseEditor *editor, + GtkTreeIter *iter, + GtkTreeIter *parent) +{ + if (editor->priv->tstore) + gtk_tree_store_append (editor->priv->tstore, iter, parent); + else + gtk_list_store_append (editor->priv->lstore, iter); +} + +static void +glade_base_editor_store_insert_after (GladeBaseEditor *editor, + GtkTreeIter *iter, + GtkTreeIter *parent, + GtkTreeIter *sibling) +{ + if (editor->priv->tstore) + gtk_tree_store_insert_after (editor->priv->tstore, iter, parent, sibling); + else + gtk_list_store_insert_after (editor->priv->lstore, iter, sibling); +} + +static gboolean +glade_base_editor_get_type_info (GladeBaseEditor *e, + GtkTreeIter *retiter, + GType child_type, + ...) +{ + GtkTreeModel *model = GTK_TREE_MODEL (e->priv->children); + GtkTreeIter iter; + GType type; + + if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) + return FALSE; + + do + { + gtk_tree_model_get (model, &iter, + GLADE_BASE_EDITOR_GTYPE, &type, + -1); + if (child_type == type) + { + va_list args; + va_start (args, child_type); + gtk_tree_model_get_valist (model, &iter, args); + va_end (args); + if (retiter) *retiter = iter; + return TRUE; + } + } while (gtk_tree_model_iter_next (model, &iter)); + + return FALSE; +} + +static gchar * +glade_base_editor_get_display_name (GladeBaseEditor *editor, + GladeWidget *gchild) +{ + gchar *retval; + g_signal_emit (editor, + glade_base_editor_signals[SIGNAL_GET_DISPLAY_NAME], + 0, gchild, &retval); + return retval; +} + +static void +glade_base_editor_fill_store_real (GladeBaseEditor *e, + GladeWidget *gwidget, + GtkTreeIter *parent) +{ + GtkWidget *widget = GTK_WIDGET (glade_widget_get_object (gwidget)); + GList *children, *l; + GtkTreeIter iter; + + children = l = glade_widget_class_container_get_children (gwidget->widget_class, + G_OBJECT (widget)); + + while (l) + { + GObject *child = (GObject*)l->data; + GladeWidget *gchild; + + if(child && (gchild = glade_widget_get_from_gobject (child))) + { + gchar *type_name, *name; + + if (glade_base_editor_get_type_info (e, NULL, + G_OBJECT_TYPE (child), + GLADE_BASE_EDITOR_NAME, &type_name, + -1)) + { + glade_base_editor_store_append (e, &iter, parent); + + name = glade_base_editor_get_display_name (e, gchild); + + glade_base_editor_store_set (e, &iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, gchild, + GLADE_BASE_EDITOR_MENU_OBJECT, child, + GLADE_BASE_EDITOR_MENU_TYPE_NAME, type_name, + GLADE_BASE_EDITOR_MENU_NAME, name, + -1); + + if (GTK_IS_CONTAINER (child)) + glade_base_editor_fill_store_real (e, gchild, &iter); + + g_free (name); + g_free (type_name); + } + else + if (GTK_IS_CONTAINER (child)) + glade_base_editor_fill_store_real (e, gchild, parent); + + } + + l = g_list_next (l); + } + + g_list_free (children); +} + +static void +glade_base_editor_fill_store (GladeBaseEditor *e) +{ + glade_base_editor_store_clear (e); + gtk_tree_view_set_model (GTK_TREE_VIEW (e->priv->treeview), NULL); + glade_base_editor_fill_store_real (e, e->priv->gcontainer, NULL); + gtk_tree_view_set_model (GTK_TREE_VIEW (e->priv->treeview), e->priv->model); +} + +static gboolean +glade_base_editor_get_child_selected (GladeBaseEditor *e, GtkTreeIter *iter) +{ + GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (e->priv->treeview)); + return gtk_tree_selection_get_selected (sel, NULL, iter); +} + +static void +glade_base_editor_name_activate (GtkEntry *entry, GladeWidget *gchild) +{ + const gchar *text = gtk_entry_get_text (GTK_ENTRY (entry)); + + if (strcmp (glade_widget_get_name (gchild), text)) + glade_command_set_name (gchild, text); +} + +static gboolean +glade_base_editor_name_focus_out (GtkWidget *entry, + GdkEventFocus *event, + GladeWidget *gchild) +{ + glade_base_editor_name_activate (GTK_ENTRY (entry), gchild); + return FALSE; +} + +static void +glade_base_editor_remove_widget (GtkWidget *widget, gpointer container) +{ + gtk_container_remove (GTK_CONTAINER (container), widget); +} + +static void +glade_base_editor_table_attach (GladeBaseEditor *e, + GtkWidget *child1, + GtkWidget *child2) +{ + GtkTable *table = GTK_TABLE (e->priv->table); + gint row = e->priv->row; + + if (child1) + { + gtk_table_attach (table, child1, 0, 1, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0); + gtk_widget_show (child1); + } + + if (child2) + { + gtk_table_attach (table, child2, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0); + gtk_widget_show (child2); + } + + e->priv->row++; +} + +static void +glade_base_editor_clear (GladeBaseEditor *editor) +{ + GladeBaseEditorPrivate *e = editor->priv; + gtk_container_foreach (GTK_CONTAINER (e->table), + glade_base_editor_remove_widget, e->table); + e->row = 0; + gtk_widget_set_sensitive (e->remove_button, FALSE); + glade_signal_editor_load_widget (e->signal_editor, NULL); +} + +static void +glade_base_editor_treeview_cursor_changed (GtkTreeView *treeview, + GladeBaseEditor *editor) +{ + GladeBaseEditorPrivate *e = editor->priv; + GtkTreeIter iter; + GObject *child; + GladeWidget *gchild; + + if (! glade_base_editor_get_child_selected (editor, &iter)) + return; + + glade_base_editor_clear (editor); + gtk_widget_set_sensitive (e->remove_button, TRUE); + + gtk_tree_model_get (e->model, &iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, &gchild, + GLADE_BASE_EDITOR_MENU_OBJECT, &child, + -1); + + /* Emit child-selected signal and let the user add the properties */ + g_signal_emit (editor, glade_base_editor_signals[SIGNAL_CHILD_SELECTED], + 0, gchild); + + /* Update Signal Editor*/ + glade_signal_editor_load_widget (e->signal_editor, gchild); +} + +static gboolean +glade_base_editor_update_properties_idle (gpointer data) +{ + glade_base_editor_treeview_cursor_changed (NULL, (GladeBaseEditor *)data); + return FALSE; +} + + +static void +glade_base_editor_update_properties (GladeBaseEditor *editor) +{ + g_idle_add (glade_base_editor_update_properties_idle, editor); +} + +static void +glade_base_editor_set_cursor (GladeBaseEditor *e, GtkTreeIter *iter) +{ + GtkTreePath *path; + GtkTreeIter real_iter; + + if (iter == NULL && + glade_base_editor_get_child_selected (e, &real_iter)) + iter = &real_iter; + + if (iter && (path = gtk_tree_model_get_path (e->priv->model, iter))) + { + gtk_tree_view_set_cursor (GTK_TREE_VIEW (e->priv->treeview), path, NULL, FALSE); + gtk_tree_path_free (path); + } +} + +static gboolean +glade_base_editor_find_child_real (GladeBaseEditor *e, + GladeWidget *gchild, + GtkTreeIter *iter) +{ + GtkTreeModel *model = e->priv->model; + GtkTreeIter child_iter; + GladeWidget *child; + + do + { + gtk_tree_model_get (model, iter, GLADE_BASE_EDITOR_MENU_GWIDGET, &child, -1); + + if (child == gchild) return TRUE; + + if (gtk_tree_model_iter_children (model, &child_iter, iter)) + if (glade_base_editor_find_child_real (e, gchild, &child_iter)) + { + *iter = child_iter; + return TRUE; + } + } + while (gtk_tree_model_iter_next (model, iter)); + + return FALSE; +} + +static gboolean +glade_base_editor_find_child (GladeBaseEditor *e, + GladeWidget *child, + GtkTreeIter *iter) +{ + if (gtk_tree_model_get_iter_first (e->priv->model, iter)) + return glade_base_editor_find_child_real (e, child, iter); + + return FALSE; +} + +static void +glade_base_editor_select_child (GladeBaseEditor *e, + GladeWidget *child) +{ + GtkTreeIter iter; + + if (glade_base_editor_find_child (e, child, &iter)) + glade_base_editor_set_cursor (e, &iter); +} + +static void +glade_base_editor_child_change_type (GladeBaseEditor *editor, + GtkTreeIter *iter, + GType type) +{ + GladeWidget *gchild; + GObject *child; + gchar *desc, *class_name; + gboolean retval; + + glade_base_editor_block_callbacks (editor, TRUE); + + /* Get old widget data */ + gtk_tree_model_get (editor->priv->model, iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, &gchild, + GLADE_BASE_EDITOR_MENU_OBJECT, &child, + -1); + + if (type == G_OBJECT_TYPE (child)) return; + + /* Start of glade-command */ + + if (glade_base_editor_get_type_info (editor, NULL, type, + GLADE_BASE_EDITOR_NAME, &class_name, + -1)) + { + desc = g_strdup_printf (_("Setting object type on %s to %s"), + glade_widget_get_name (gchild), + class_name); + glade_command_push_group (desc); + g_free (class_name); + g_free (desc); + } + else return; + + g_signal_emit (editor, + glade_base_editor_signals [SIGNAL_CHANGE_TYPE], + 0, gchild, type, &retval); + + /* End of glade-command */ + glade_command_pop_group (); + + /* Update properties */ + glade_base_editor_update_properties (editor); + + glade_base_editor_block_callbacks (editor, FALSE); +} + +static void +glade_base_editor_type_changed (GtkComboBox *widget, GladeBaseEditor *e) +{ + GtkTreeIter iter, combo_iter; + GType type; + + if (! glade_base_editor_get_child_selected (e, &iter)) + return; + + gtk_combo_box_get_active_iter (widget, &combo_iter); + + gtk_tree_model_get (gtk_combo_box_get_model (widget), &combo_iter, + GLADE_BASE_EDITOR_GTYPE, &type, -1); + + glade_base_editor_child_change_type (e, &iter, type); +} + +static void +glade_base_editor_child_type_edited (GtkCellRendererText *cell, + const gchar *path_string, + const gchar *new_text, + GladeBaseEditor *editor) +{ + GladeBaseEditorPrivate *e = editor->priv; + GtkTreeModel *child_class = GTK_TREE_MODEL (e->children); + GtkTreePath *path; + GtkTreeIter iter, combo_iter; + GType type; + gchar *type_name; + + path = gtk_tree_path_new_from_string (path_string); + gtk_tree_model_get_iter (e->model, &iter, path); + gtk_tree_model_get (e->model, &iter, + GLADE_BASE_EDITOR_MENU_TYPE_NAME, &type_name, + -1); + if (strcmp (type_name, new_text) == 0) + { + g_free (type_name); + return; + } + + /* Lookup GladeWidgetClass */ + gtk_tree_model_get_iter_first (child_class, &combo_iter); + do + { + gtk_tree_model_get (child_class, &combo_iter, + GLADE_BASE_EDITOR_GTYPE, &type, + GLADE_BASE_EDITOR_NAME, &type_name, + -1); + + if (strcmp (type_name, new_text) == 0) break; + + g_free (type_name); + } while (gtk_tree_model_iter_next (child_class, &combo_iter)); + + glade_base_editor_child_change_type (editor, &iter, type); +} + +static gint +glade_base_editor_popup_handler (GtkWidget *treeview, + GdkEventButton *event, + GladeBaseEditor *e) +{ + GtkTreePath *path; + + if (event->button == 3) + { + if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview), + (gint) event->x, (gint) event->y, &path, NULL, NULL, NULL)) + { + gtk_tree_view_set_cursor (GTK_TREE_VIEW (treeview), path, NULL, FALSE); + gtk_tree_path_free (path); + } + + gtk_menu_popup (GTK_MENU (e->priv->popup), NULL, NULL, NULL, NULL, + event->button, event->time); + return TRUE; + } + + return FALSE; +} + +static void +glade_base_editor_reorder_children (GladeBaseEditor *editor, GtkTreeIter *child) +{ + GtkTreeModel *model = editor->priv->model; + GladeWidget *gchild; + GladeProperty *property; + GtkTreeIter parent, iter; + GValue val = {0, }; + gint position = 0; + + if (gtk_tree_model_iter_parent (model, &parent, child)) + gtk_tree_model_iter_children (model, &iter, &parent); + else + gtk_tree_model_get_iter_first (model, &iter); + + g_value_init (&val, G_TYPE_INT); + + do + { + gtk_tree_model_get (model, &iter, GLADE_BASE_EDITOR_MENU_GWIDGET, &gchild, -1); + g_value_set_int (&val, position++); + + if ((property = glade_widget_get_property (gchild, "position")) != NULL) + glade_command_set_property (property, &val); + } while (gtk_tree_model_iter_next (model, &iter)); +} + +static void +glade_base_editor_add_child (GladeBaseEditor *editor, + GType type, + gboolean as_child) +{ + GladeBaseEditorPrivate *e = editor->priv; + GtkTreeIter iter, new_iter; + GladeWidget *gparent, *gchild = NULL, *gchild_new; + gchar *desc, *type_name, *name, *class_name; + + if (glade_base_editor_get_type_info (editor, NULL, type, + GLADE_BASE_EDITOR_NAME, &class_name, + -1) == FALSE) return; + + glade_base_editor_block_callbacks (editor, TRUE); + + gparent = e->gcontainer; + + if (glade_base_editor_get_child_selected (editor, &iter)) + { + gtk_tree_model_get (e->model, &iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, &gchild, + -1); + if (as_child) + { + glade_base_editor_store_append (editor, &new_iter, &iter); + gparent = gchild; + } + else + { + glade_base_editor_store_insert_after (editor, &new_iter, + NULL, &iter); + gparent = glade_widget_get_parent (gchild); + } + + } + else + glade_base_editor_store_append (editor, &new_iter, NULL); + + desc = g_strdup_printf (_("Add a %s to %s"), class_name, + glade_widget_get_name (gparent)); + glade_command_push_group (desc); + g_free (class_name); + g_free (desc); + + /* Build Child */ + g_signal_emit (editor, glade_base_editor_signals[SIGNAL_BUILD_CHILD], + 0, gparent, type, &gchild_new); + + if (gchild_new == NULL) + { + glade_command_pop_group (); + glade_base_editor_store_remove (editor, &new_iter); + return; + } + + glade_base_editor_get_type_info (editor, NULL, type, + GLADE_BASE_EDITOR_NAME, &type_name, + -1); + + name = glade_base_editor_get_display_name (editor, gchild_new); + + glade_base_editor_store_set (editor, &new_iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, gchild_new, + GLADE_BASE_EDITOR_MENU_OBJECT, glade_widget_get_object (gchild_new), + GLADE_BASE_EDITOR_MENU_TYPE_NAME, type_name, + GLADE_BASE_EDITOR_MENU_NAME, name, + -1); + + glade_base_editor_reorder_children (editor, &new_iter); + + gtk_tree_view_expand_all (GTK_TREE_VIEW (e->treeview)); + glade_base_editor_set_cursor (editor, &new_iter); + + glade_command_pop_group (); + + glade_base_editor_block_callbacks (editor, FALSE); + + g_free (name); + g_free (type_name); +} + +static void +glade_base_editor_add_item_activate (GtkMenuItem *menuitem, GladeBaseEditor *e) +{ + GObject *item = G_OBJECT (menuitem); + GType type = GPOINTER_TO_INT (g_object_get_data (item, "object_type")); + gboolean as_child = GPOINTER_TO_INT (g_object_get_data (item, "object_as_child")); + + glade_base_editor_add_child (e, type, as_child); +} + +static void +glade_base_editor_add_activate (GtkButton *button, GladeBaseEditor *e) +{ + if (e->priv->add_type) + glade_base_editor_add_child (e, e->priv->add_type, e->priv->add_as_child); +} + +static void +glade_base_editor_delete_child (GladeBaseEditor *e) +{ + GladeWidget *child, *gparent; + GtkTreeIter iter, parent; + gchar *desc; + + if (glade_base_editor_get_child_selected (e, &iter) == FALSE) return; + + gtk_tree_model_get (e->priv->model, &iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, &child, -1); + + if (gtk_tree_model_iter_parent (e->priv->model, &parent, &iter)) + gtk_tree_model_get (e->priv->model, &parent, + GLADE_BASE_EDITOR_MENU_GWIDGET, &gparent, + -1); + else + gparent = e->priv->gcontainer; + + desc = g_strdup_printf (_("Delete %s child from %s"), + glade_widget_get_name (child), + glade_widget_get_name (gparent)); + glade_command_push_group (desc); + g_free (desc); + + /* Emit delete-child signal */ + g_signal_emit (e, glade_base_editor_signals[SIGNAL_DELETE_CHILD], + 0, gparent, child); + + glade_command_pop_group (); +} + + +static gboolean +glade_base_editor_treeview_key_press_event (GtkWidget *widget, + GdkEventKey *event, + GladeBaseEditor *e) +{ + if (event->keyval == GDK_Delete) + glade_base_editor_delete_child (e); + + return FALSE; +} + +static void +glade_base_editor_delete_activate (GtkButton *button, GladeBaseEditor *e) +{ + glade_base_editor_delete_child (e); +} + +static gboolean +glade_base_editor_is_child (GladeBaseEditor *e, + GladeWidget *gchild, + gboolean valid_type) +{ + GladeWidget *gcontainer; + + if (valid_type) + { + GObject *child = glade_widget_get_object (gchild); + + gcontainer = e->priv->gcontainer; + + if (gchild->internal || + glade_base_editor_get_type_info (e, NULL, + G_OBJECT_TYPE (child), + -1) == FALSE) + return FALSE; + } + else + { + GtkTreeIter iter; + if (glade_base_editor_get_child_selected (e, &iter)) + gtk_tree_model_get (e->priv->model, &iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, &gcontainer, + -1); + else + return FALSE; + } + + while ((gchild = glade_widget_get_parent (gchild))) + if (gchild == gcontainer) return TRUE; + + return FALSE; +} + +static gboolean +glade_base_editor_update_treeview_idle (gpointer data) +{ + GladeBaseEditor *e = ((GladeBaseEditor *) data); + GList *selection = glade_project_selection_get (e->priv->project); + + glade_base_editor_block_callbacks (e, TRUE); + + glade_base_editor_fill_store (e); + glade_base_editor_clear (e); + + gtk_tree_view_expand_all (GTK_TREE_VIEW (e->priv->treeview)); + + if (selection) + { + GladeWidget *widget = glade_widget_get_from_gobject (G_OBJECT (selection->data)); + if (glade_base_editor_is_child (e, widget, TRUE)) + glade_base_editor_select_child (e, widget); + } + + e->priv->updating_treeview = FALSE; + glade_base_editor_block_callbacks (e, FALSE); + + return FALSE; +} + +static void +glade_base_editor_project_widget_name_changed (GladeProject *project, + GladeWidget *widget, + GladeBaseEditor *editor) +{ + GladeWidget *selected_child; + GtkTreeIter iter; + + if (glade_base_editor_get_child_selected (editor, &iter)) + { + gtk_tree_model_get (editor->priv->model, &iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, &selected_child, + -1); + if (widget == selected_child) + glade_base_editor_update_properties (editor); + } +} + +static void +glade_base_editor_project_closed (GladeProject *project, GladeBaseEditor *e) +{ + glade_base_editor_set_container (e, NULL); +} + +static void +glade_base_editor_reorder (GladeBaseEditor *editor, GtkTreeIter *iter) +{ + GladeBaseEditorPrivate *e = editor->priv; + GladeWidget *gchild, *gparent; + GtkTreeIter parent_iter; + gchar *desc; + gboolean retval; + + desc = g_strdup_printf (_("Reorder %s's children"), + glade_widget_get_name (e->gcontainer)); + glade_command_push_group (desc); + g_free (desc); + + gtk_tree_model_get (e->model, iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, &gchild, -1); + + if (gtk_tree_model_iter_parent (e->model, &parent_iter, iter)) + gtk_tree_model_get (e->model, &parent_iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, &gparent, + -1); + else + gparent = e->gcontainer; + + g_signal_emit (editor, glade_base_editor_signals [SIGNAL_MOVE_CHILD], + 0, gparent, gchild, &retval); + + if (retval) + glade_base_editor_reorder_children (editor, iter); + else + { + glade_base_editor_clear (editor); + glade_base_editor_fill_store (editor); + glade_base_editor_find_child (editor, gparent, &editor->priv->iter); + } + + glade_command_pop_group (); +} + +static gboolean +glade_base_editor_drag_and_drop_idle (gpointer data) +{ + GladeBaseEditor *e = (GladeBaseEditor *) data; + + glade_base_editor_reorder (e, &e->priv->iter); + gtk_tree_view_expand_all (GTK_TREE_VIEW (e->priv->treeview)); + glade_base_editor_set_cursor (e, &e->priv->iter); + glade_base_editor_block_callbacks (e, FALSE); + + return FALSE; +} + +static void +glade_base_editor_row_inserted (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + GladeBaseEditor *e) +{ + e->priv->iter = *iter; + glade_base_editor_block_callbacks (e, TRUE); + g_idle_add (glade_base_editor_drag_and_drop_idle, e); +} + +static void +glade_base_editor_project_remove_widget (GladeProject *project, + GladeWidget *widget, + GladeBaseEditor *e) +{ + if (widget == e->priv->gcontainer) + { + glade_base_editor_set_container (e, NULL); + return; + } + + if (glade_base_editor_is_child (e, widget, TRUE)) + { + GtkTreeIter iter; + if (glade_base_editor_find_child (e, widget, &iter)) + { + glade_base_editor_store_remove (e, &iter); + glade_base_editor_clear (e); + } + } + + if (widget->internal && + glade_base_editor_is_child (e, widget, FALSE)) + glade_base_editor_update_properties (e); +} + +static void +glade_base_editor_project_add_widget (GladeProject *project, + GladeWidget *widget, + GladeBaseEditor *e) +{ + if (e->priv->updating_treeview) return; + + if (glade_base_editor_is_child (e, widget, TRUE)) + { + e->priv->updating_treeview = TRUE; + g_idle_add (glade_base_editor_update_treeview_idle, e); + } + + if (widget->internal && + glade_base_editor_is_child (e, widget, FALSE)) + glade_base_editor_update_properties (e); +} + +static gboolean +glade_base_editor_update_display_name (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) +{ + GladeBaseEditor *editor = (GladeBaseEditor *) data; + GladeWidget *gchild; + gchar *name; + + gtk_tree_model_get (model, iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, &gchild, + -1); + + name = glade_base_editor_get_display_name (editor, gchild); + + glade_base_editor_store_set (editor, iter, + GLADE_BASE_EDITOR_MENU_NAME, name, + -1); + g_free (name); + + return FALSE; +} + +static void +glade_base_editor_project_changed (GladeProject *project, + GladeCommand *command, + gboolean forward, + GladeBaseEditor *editor) +{ + gtk_tree_model_foreach (editor->priv->model, + glade_base_editor_update_display_name, + editor); +} + + + +static void +glade_base_editor_project_disconnect (GladeBaseEditor *editor) +{ + GladeBaseEditorPrivate *e = editor->priv; + + if (e->project == NULL) return; + + g_signal_handlers_disconnect_by_func (e->project, + glade_base_editor_project_closed, editor); + + g_signal_handlers_disconnect_by_func (e->project, + glade_base_editor_project_remove_widget, editor); + + g_signal_handlers_disconnect_by_func (e->project, + glade_base_editor_project_add_widget, editor); + + g_signal_handlers_disconnect_by_func (e->project, + glade_base_editor_project_widget_name_changed, editor); + + g_signal_handlers_disconnect_by_func (e->project, + glade_base_editor_project_changed, editor); +} + +static void +glade_base_editor_set_container (GladeBaseEditor *editor, + GObject *container) +{ + GladeBaseEditorPrivate *e = editor->priv; + + if (e->project) + glade_base_editor_project_disconnect (editor); + + if (container == NULL) + { + e->gcontainer = NULL; + e->project = NULL; + glade_base_editor_block_callbacks (editor, TRUE); + glade_base_editor_clear (editor); + glade_base_editor_store_clear (editor); + gtk_list_store_clear (e->children); + gtk_widget_set_sensitive (e->paned, FALSE); + glade_base_editor_block_callbacks (editor, FALSE); + return; + } + + gtk_widget_set_sensitive (e->paned, TRUE); + + e->gcontainer = glade_widget_get_from_gobject (container); + + e->project = glade_widget_get_project (e->gcontainer); + + g_signal_connect (e->project, "close", + G_CALLBACK (glade_base_editor_project_closed), + editor); + + g_signal_connect (e->project, "remove-widget", + G_CALLBACK (glade_base_editor_project_remove_widget), + editor); + + g_signal_connect (e->project, "add-widget", + G_CALLBACK (glade_base_editor_project_add_widget), + editor); + + g_signal_connect (e->project, "widget-name-changed", + G_CALLBACK (glade_base_editor_project_widget_name_changed), + editor); + + g_signal_connect (e->project, "changed", + G_CALLBACK (glade_base_editor_project_changed), + editor); +} + +/*************************** GladeBaseEditor Class ****************************/ + +static void +glade_base_editor_finalize (GObject *object) +{ + GladeBaseEditor *cobj = GLADE_BASE_EDITOR (object); + + /* Free private members, etc. */ + glade_base_editor_project_disconnect (cobj); + + g_free (cobj->priv); + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +/* Default handlers */ +static gboolean +glade_base_editor_change_type (GladeBaseEditor *editor, + GladeWidget *gchild, + GType type) +{ + GladeBaseEditorPrivate *e = editor->priv; + GladeWidgetClass *klass = glade_widget_class_get_by_type (type); + GladeWidget *parent, *gchild_new; + GList list = {0, }, *children, *l; + GObject *child, *child_new; + GtkTreeIter iter; + gchar *name, *class_name; + + if (glade_base_editor_get_type_info (editor, NULL, type, + GLADE_BASE_EDITOR_NAME, &class_name, + -1) == FALSE) + return TRUE; + + parent = glade_widget_get_parent (gchild); + child = glade_widget_get_object (gchild); + name = g_strdup (glade_widget_get_name (gchild)); + glade_base_editor_find_child (editor, gchild, &iter); + + /* Create new widget */ + gchild_new = glade_command_create (klass, parent, NULL, e->project); + child_new = glade_widget_get_object (gchild_new); + + /* Cut and Paste childrens */ + if ((children = glade_widget_class_container_get_children (klass, child))) + { + GList *gchildren = NULL; + + l = children; + while (l) + { + GladeWidget *w = glade_widget_get_from_gobject (l->data); + + if (w && !w->internal) + gchildren = g_list_prepend (gchildren, w); + + l= g_list_next (l); + } + + if (gchildren) + { + glade_command_cut (gchildren); + glade_command_paste (gchildren, gchild_new, NULL); + + g_list_free (children); + g_list_free (gchildren); + } + } + + /* Copy properties */ + glade_widget_copy_properties (gchild_new, gchild); + + /* Delete old widget */ + list.data = gchild; + glade_command_delete (&list); + + /* Apply packing properties to the new object */ + l = gchild->packing_properties; + while (l) + { + GladeProperty *orig_prop = (GladeProperty *) l->data; + GladeProperty *dup_prop = glade_widget_get_property (gchild_new, + orig_prop->class->id); + glade_property_set_value (dup_prop, orig_prop->value); + l = g_list_next (l); + } + + /* Set the name */ + glade_widget_set_name (gchild_new, name); + + if (GTK_IS_WIDGET (child_new)) + gtk_widget_show_all (GTK_WIDGET (child_new)); + + glade_base_editor_store_set (editor, &iter, + GLADE_BASE_EDITOR_MENU_GWIDGET, gchild_new, + GLADE_BASE_EDITOR_MENU_OBJECT, child_new, + GLADE_BASE_EDITOR_MENU_TYPE_NAME, class_name, + -1); + g_free (class_name); + g_free (name); + + return TRUE; +} + +static gchar * +glade_base_editor_get_display_name_impl (GladeBaseEditor *editor, + GladeWidget *gchild) +{ + return g_strdup (glade_widget_get_name (gchild)); +} + +static GladeWidget * +glade_base_editor_build_child (GladeBaseEditor *editor, + GladeWidget *gparent, + GType type) +{ + return glade_command_create (glade_widget_class_get_by_type (type), + gparent, NULL, + glade_widget_get_project (gparent)); +} + +static gboolean +glade_base_editor_move_child (GladeBaseEditor *editor, + GladeWidget *gparent, + GladeWidget *gchild) +{ + GList list = {0, }; + + list.data = gchild; + glade_command_cut (&list); + glade_command_paste (&list, gparent, NULL); + + return TRUE; +} + +static gboolean +glade_base_editor_delete_child_impl (GladeBaseEditor *editor, + GladeWidget *gparent, + GladeWidget *gchild) +{ + GList list = {0, }; + + list.data = gchild; + glade_command_delete (&list); + + return TRUE; +} + +static void +glade_base_editor_class_init (GladeBaseEditorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + object_class->finalize = glade_base_editor_finalize; + + klass->change_type = glade_base_editor_change_type; + klass->get_display_name = glade_base_editor_get_display_name_impl; + klass->build_child = glade_base_editor_build_child; + klass->delete_child = glade_base_editor_delete_child_impl; + klass->move_child = glade_base_editor_move_child; + + /** + * GladeBaseEditor::child-selected: + * @gladebaseeditor: the #GladeBaseEditor which received the signal. + * @gchild: the selected #GladeWidget. + * + * Emited when the user selects a child in the editor's treeview. + * You can add the relevant child properties here using + * glade_base_editor_add_default_properties() and glade_base_editor_add_properties() + * You can also add labels with glade_base_editor_add_label to make the + * editor look pretty. + */ + glade_base_editor_signals [SIGNAL_CHILD_SELECTED] = + g_signal_new ("child-selected", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GladeBaseEditorClass, child_selected), + NULL, NULL, + glade_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + G_TYPE_OBJECT); + + /** + * GladeBaseEditor::child-change-type: + * @gladebaseeditor: the #GladeBaseEditor which received the signal. + * @child: the #GObject being changed. + * @type: the new type for @child. + * + * Returns TRUE to stop signal emision. + */ + glade_base_editor_signals [SIGNAL_CHANGE_TYPE] = + g_signal_new ("change-type", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GladeBaseEditorClass, change_type), + glade_boolean_handled_accumulator, NULL, + glade_marshal_BOOLEAN__OBJECT_UINT, + G_TYPE_BOOLEAN, + 2, + G_TYPE_OBJECT, G_TYPE_UINT); + + /** + * GladeBaseEditor::get-display-name: + * @gladebaseeditor: the #GladeBaseEditor which received the signal. + * @gchild: the child to get display name string to show in @gladebaseeditor + * treeview. + * + * Returns a newly allocated string. + */ + glade_base_editor_signals [SIGNAL_GET_DISPLAY_NAME] = + g_signal_new ("get-display-name", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GladeBaseEditorClass, get_display_name), + glade_string_accumulator, NULL, + glade_marshal_STRING__OBJECT, + G_TYPE_STRING, + 1, + G_TYPE_OBJECT); + + /** + * GladeBaseEditor::build-child: + * @gladebaseeditor: the #GladeBaseEditor which received the signal. + * @gparent: the parent of the new child + * @type: the #GType of the child + * + * Create a child widget here if something else must be done other than + * calling glade_command_create() such as creating an intermediate parent. + * Returns the newly created #GladeWidget or NULL if child cant be created + */ + glade_base_editor_signals [SIGNAL_BUILD_CHILD] = + g_signal_new ("build-child", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GladeBaseEditorClass, build_child), + glade_stop_emission_accumulator, NULL, + glade_marshal_OBJECT__OBJECT_UINT, + G_TYPE_OBJECT, + 2, + G_TYPE_OBJECT, G_TYPE_UINT); + + /** + * GladeBaseEditor::delete-child: + * @gladebaseeditor: the #GladeBaseEditor which received the signal. + * @gparent: the parent + * @gchild: the child to delete + */ + glade_base_editor_signals [SIGNAL_DELETE_CHILD] = + g_signal_new ("delete-child", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GladeBaseEditorClass, delete_child), + glade_boolean_handled_accumulator, NULL, + glade_marshal_BOOLEAN__OBJECT_OBJECT, + G_TYPE_BOOLEAN, + 2, + G_TYPE_OBJECT, G_TYPE_OBJECT); + + /** + * GladeBaseEditor::move-child: + * @gladebaseeditor: the #GladeBaseEditor which received the signal. + * @gparent: the new parent of @gchild + * @gchild: the #GladeWidget to move + * + * Move child here if something else must be done other than cut & paste. + * Returns wheater child has been sucessfully moved or not. + */ + glade_base_editor_signals [SIGNAL_MOVE_CHILD] = + g_signal_new ("move-child", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GladeBaseEditorClass, move_child), + glade_stop_emission_accumulator, NULL, + glade_marshal_BOOLEAN__OBJECT_OBJECT, + G_TYPE_BOOLEAN, + 2, + G_TYPE_OBJECT, G_TYPE_OBJECT); +} + +static void +glade_base_editor_block_callbacks (GladeBaseEditor *editor, gboolean block) +{ + GladeBaseEditorPrivate *e = editor->priv; + if (block) + { + g_signal_handlers_block_by_func (e->model, glade_base_editor_row_inserted, editor); + if (e->project) + { + g_signal_handlers_block_by_func (e->project, glade_base_editor_project_remove_widget, editor); + g_signal_handlers_block_by_func (e->project, glade_base_editor_project_add_widget, editor); + g_signal_handlers_block_by_func (e->project, glade_base_editor_project_changed, editor); + } + } + else + { + g_signal_handlers_unblock_by_func (e->model, glade_base_editor_row_inserted, editor); + if (e->project) + { + g_signal_handlers_unblock_by_func (e->project, glade_base_editor_project_remove_widget, editor); + g_signal_handlers_unblock_by_func (e->project, glade_base_editor_project_add_widget, editor); + g_signal_handlers_unblock_by_func (e->project, glade_base_editor_project_changed, editor); + } + } +} + +static void +glade_base_editor_realize_callback (GtkWidget *widget, gpointer user_data) +{ + GladeBaseEditor *editor = GLADE_BASE_EDITOR (widget); + + glade_base_editor_block_callbacks (editor, TRUE); + + glade_base_editor_fill_store (editor); + gtk_tree_view_expand_all (GTK_TREE_VIEW (editor->priv->treeview)); + + glade_base_editor_block_callbacks (editor, FALSE); +} + +static void +glade_base_editor_init (GladeBaseEditor *editor) +{ + GladeBaseEditorPrivate *e; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + GtkWidget *paned, *hbox, *vbox, *tree_vbox, *scroll, *button_table, *button; + + gtk_box_set_spacing (GTK_BOX (editor), 8); + + e = editor->priv = g_new0(GladeBaseEditorPrivate, 1); + + /* Children store */ + e->children = gtk_list_store_new (GLADE_BASE_EDITOR_N_COLUMNS, + G_TYPE_UINT, G_TYPE_STRING); + + /* Paned */ + e->paned = paned = gtk_vpaned_new (); + gtk_widget_show (paned); + gtk_box_pack_start (GTK_BOX (editor), paned, TRUE, TRUE, 0); + + /* Hbox */ + hbox = gtk_hbox_new (FALSE, 8); + gtk_widget_show (hbox); + gtk_paned_pack1 (GTK_PANED (paned), hbox, TRUE, FALSE); + + /* TreeView Vbox */ + tree_vbox = gtk_vbox_new (FALSE, 8); + gtk_widget_show (tree_vbox); + gtk_box_pack_start (GTK_BOX (hbox), tree_vbox, FALSE, TRUE, 0); + + /* ScrolledWindow */ + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scroll); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + gtk_box_pack_start (GTK_BOX (tree_vbox), scroll, TRUE, TRUE, 0); + + /* TreeView */ + e->treeview = gtk_tree_view_new (); + gtk_widget_show (e->treeview); + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (e->treeview), TRUE); + gtk_tree_view_set_reorderable (GTK_TREE_VIEW (e->treeview), TRUE); + + gtk_widget_add_events (e->treeview, GDK_KEY_PRESS_MASK); + g_signal_connect (e->treeview, "key-press-event", + G_CALLBACK (glade_base_editor_treeview_key_press_event), editor); + + g_signal_connect (e->treeview, "cursor-changed", + G_CALLBACK (glade_base_editor_treeview_cursor_changed), editor); + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes (_("Label"), renderer, + "text", GLADE_BASE_EDITOR_MENU_NAME, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (e->treeview), column); + + renderer = gtk_cell_renderer_combo_new (); + g_object_set (renderer, + "model", e->children, + "text-column", GLADE_BASE_EDITOR_NAME, + "has-entry", FALSE, + "editable", TRUE, + NULL); + g_signal_connect (renderer, "edited", + G_CALLBACK (glade_base_editor_child_type_edited), editor); + column = gtk_tree_view_column_new_with_attributes (_("Type"), renderer, + "text", GLADE_BASE_EDITOR_MENU_TYPE_NAME, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (e->treeview), column); + + gtk_container_add (GTK_CONTAINER (scroll), e->treeview); + + /* Add/Remove buttons */ + button_table = gtk_table_new (1, 2, TRUE); + gtk_widget_show (button_table); + gtk_table_set_col_spacings (GTK_TABLE (button_table), 8); + gtk_box_pack_start (GTK_BOX (tree_vbox), button_table, FALSE, TRUE, 0); + + button = gtk_button_new_from_stock (GTK_STOCK_ADD); + gtk_widget_show (button); + g_signal_connect (button, "clicked", + G_CALLBACK (glade_base_editor_add_activate), editor); + gtk_table_attach_defaults (GTK_TABLE (button_table), button, 0, 1, 0, 1); + + e->remove_button = button = gtk_button_new_from_stock (GTK_STOCK_REMOVE); + gtk_widget_show (button); + g_signal_connect (button, "clicked", + G_CALLBACK (glade_base_editor_delete_activate), editor); + gtk_table_attach_defaults (GTK_TABLE (button_table), button, 1, 2, 0, 1); + + /* Properties Vbox */ + vbox = gtk_vbox_new (FALSE, 8); + gtk_widget_show (vbox); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); + + /* Tables */ + e->table = gtk_table_new (1, 2, FALSE); + gtk_widget_show (e->table); + gtk_table_set_row_spacings (GTK_TABLE (e->table), 4); + gtk_box_pack_start (GTK_BOX (vbox), e->table, FALSE, TRUE, 0); + + /* Signal Editor */ + e->signal_editor = glade_signal_editor_new (NULL); + e->signal_editor_w = glade_signal_editor_get_widget (e->signal_editor); + gtk_widget_show (e->signal_editor_w); + gtk_widget_set_size_request (e->signal_editor_w, -1, 96); + gtk_paned_pack2 (GTK_PANED (paned), e->signal_editor_w, FALSE, FALSE); + + /* Update the treeview on realize event */ + g_signal_connect (editor, "realize", + G_CALLBACK (glade_base_editor_realize_callback), + NULL); +} + +/********************************* Public API *********************************/ +GType +glade_base_editor_get_type () +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo our_info = { + sizeof (GladeBaseEditorClass), + NULL, + NULL, + (GClassInitFunc)glade_base_editor_class_init, + NULL, + NULL, + sizeof (GladeBaseEditor), + 0, + (GInstanceInitFunc)glade_base_editor_init, + }; + + type = g_type_register_static (GTK_TYPE_VBOX, "GladeBaseEditor", + &our_info, 0); + } + + return type; +} + +/** + * glade_base_editor_new: + * @container: the container this new editor will edit. + * @tree_like: TRUE if container's children can have children. + * @... A NULL terminated list of gchar *, GType + * + * Creates a new GladeBaseEditor with support for all the object types indicated + * in the variable argument list. + * Argument List: + * o The type name + * o The GType the editor will support + * + * Returns a new GladeBaseEditor. + */ +GladeBaseEditor * +glade_base_editor_new (GObject *container, gboolean tree_like, ...) +{ + GladeBaseEditor *editor; + GladeBaseEditorPrivate *e; + va_list args; + gchar *name; + GtkTreeIter iter; + + g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL); + + editor = GLADE_BASE_EDITOR (g_object_new (GLADE_TYPE_BASE_EDITOR, NULL)); + e = editor->priv; + + /* Store */ + if (tree_like) + { + e->tstore = gtk_tree_store_new (GLADE_BASE_EDITOR_MENU_N_COLUMNS, + G_TYPE_OBJECT, + G_TYPE_OBJECT, + G_TYPE_STRING, + G_TYPE_STRING); + e->model = GTK_TREE_MODEL (e->tstore); + } + else + { + e->lstore = gtk_list_store_new (GLADE_BASE_EDITOR_MENU_N_COLUMNS, + G_TYPE_OBJECT, + G_TYPE_OBJECT, + G_TYPE_STRING, + G_TYPE_STRING); + e->model = GTK_TREE_MODEL (e->lstore); + } + + gtk_tree_view_set_model (GTK_TREE_VIEW (e->treeview), e->model); + gtk_tree_view_expand_all (GTK_TREE_VIEW (e->treeview)); + + g_signal_connect (e->model, "row-inserted", + G_CALLBACK (glade_base_editor_row_inserted), + editor); + + va_start (args, tree_like); + + while ((name = va_arg (args, gchar *))) + { + gtk_list_store_append (editor->priv->children, &iter); + gtk_list_store_set (editor->priv->children, &iter, + GLADE_BASE_EDITOR_GTYPE, va_arg (args, GType), + GLADE_BASE_EDITOR_NAME, name, + -1); + } + + va_end (args); + + glade_base_editor_set_container (editor, container); + + return editor; +} + + +/** + * glade_base_editor_add_default_properties: + * @editor: a #GladeBaseEditor + * @gchild: a #GladeWidget + * + * Add @gchild name and type property to @editor + * + * NOTE: This function is intended to be used in "child-selected" callbacks + */ +void +glade_base_editor_add_default_properties (GladeBaseEditor *editor, + GladeWidget *gchild) +{ + GladeBaseEditorPrivate *e = editor->priv; + GtkTreeIter combo_iter; + GtkWidget *label, *entry; + GtkTreeModel *child_class = GTK_TREE_MODEL (e->children); + GtkCellRenderer *renderer; + gboolean retval; + GObject *child = glade_widget_get_object (gchild); + + g_return_if_fail (GLADE_IS_BASE_EDITOR (editor)); + g_return_if_fail (GLADE_IS_WIDGET (gchild)); + + /* Name */ + label = gtk_label_new (_("Name :")); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.0); + + entry = gtk_entry_new (); + gtk_entry_set_text (GTK_ENTRY (entry), glade_widget_get_name (gchild)); + g_signal_connect (entry, "activate", G_CALLBACK (glade_base_editor_name_activate), gchild); + g_signal_connect (entry, "focus-out-event", G_CALLBACK (glade_base_editor_name_focus_out), gchild); + glade_base_editor_table_attach (editor, label, entry); + + /* Type */ + label = gtk_label_new (_("Type :")); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.0); + + entry = gtk_combo_box_new (); + gtk_combo_box_set_model (GTK_COMBO_BOX (entry), child_class); + + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (entry), renderer, FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (entry), renderer, "text", + GLADE_BASE_EDITOR_NAME, NULL); + + if ((retval = glade_base_editor_get_type_info (editor, &combo_iter, G_OBJECT_TYPE (child), -1))) + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (entry), &combo_iter); + + g_signal_connect (entry, "changed", G_CALLBACK (glade_base_editor_type_changed), editor); + glade_base_editor_table_attach (editor, label, entry); +} + +/** + * glade_base_editor_add_properties: + * @editor: a #GladeBaseEditor + * @gchild: a #GladeWidget + * @...: A NULL terminated list of properties names. + * + * Add @gchild properties to @editor + * + * NOTE: This function is intended to be used in "child-selected" callbacks + */ +void +glade_base_editor_add_properties (GladeBaseEditor *editor, + GladeWidget *gchild, + ...) +{ + GladeEditorProperty *eprop; + va_list args; + gchar *property; + + g_return_if_fail (GLADE_IS_BASE_EDITOR (editor)); + g_return_if_fail (GLADE_IS_WIDGET (gchild)); + + va_start (args, gchild); + property = va_arg (args, gchar *); + + while (property) + { + eprop = glade_editor_property_new_from_widget (gchild, property, TRUE); + if (eprop) + glade_base_editor_table_attach (editor, + GLADE_EDITOR_PROPERTY (eprop)->eventbox, + GTK_WIDGET (eprop)); + property = va_arg (args, gchar *); + } +} + +/** + * glade_base_editor_add_label: + * @editor: a #GladeBaseEditor + * @str: the label string + * + * Adds a new label to @editor + * + * NOTE: This function is intended to be used in "child-selected" callbacks + */ +void +glade_base_editor_add_label (GladeBaseEditor *editor, gchar *str) +{ + GtkWidget *label; + gchar *markup; + gint row; + + g_return_if_fail (GLADE_IS_BASE_EDITOR (editor)); + g_return_if_fail (str != NULL); + + label = gtk_label_new (NULL); + markup = g_strdup_printf ("<span rise=\"-20000\"><b>%s</b></span>", str); + row = editor->priv->row; + + gtk_label_set_markup (GTK_LABEL (label), markup); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); + gtk_table_attach (GTK_TABLE (editor->priv->table), label, 0, 2, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0); + gtk_widget_show (label); + editor->priv->row++; + + g_free (markup); +} + +/** + * glade_base_editor_add_popup_items: + * @editor: a #GladeBaseEditor + * @...: a NULL terminated list of gchar *, #GType, gboolean + * + * Adds a new popup item to the editor. + * Three parameters are needed for each new popup item: + * o the popup item's label + * o the object type this popup item will create + * o whether this popup item will add the new object as child + */ +void +glade_base_editor_add_popup_items (GladeBaseEditor *editor, ...) +{ + va_list args; + GtkMenuShell *menu; + GtkWidget *item; + gchar *label; + GType type; + gboolean as_child; + + g_return_if_fail (GLADE_IS_BASE_EDITOR (editor)); + + if (editor->priv->popup == NULL) + { + /* Create PopUp */ + editor->priv->popup = gtk_menu_new (); + gtk_widget_show (editor->priv->popup); + g_signal_connect (editor->priv->treeview, "button-press-event", + G_CALLBACK (glade_base_editor_popup_handler), + editor); + } + + menu = GTK_MENU_SHELL (editor->priv->popup); + + va_start (args, editor); + + while ((label = va_arg (args, gchar *))) + { + type = va_arg (args, GType); + as_child = va_arg (args, gboolean); + + if (!glade_base_editor_get_type_info (editor, NULL, type, -1)) + continue; + + item = gtk_menu_item_new_with_label (label); + gtk_widget_show (item); + + g_object_set_data (G_OBJECT (item), "object_type", + GINT_TO_POINTER (type)); + + g_object_set_data (G_OBJECT (item), "object_as_child", + GINT_TO_POINTER (as_child)); + + if (editor->priv->add_type == 0) + { + editor->priv->add_type = type; + editor->priv->add_as_child = as_child; + } + + g_signal_connect (item, "activate", + G_CALLBACK (glade_base_editor_add_item_activate), editor); + gtk_menu_shell_append (menu, item); + } +} + +/** + * glade_base_editor_set_show_signal_editor: + * @editor: a #GladeBaseEditor + * @val: + * + * Shows/hide @editor 's signal editor + */ +void +glade_base_editor_set_show_signal_editor (GladeBaseEditor *editor, gboolean val) +{ + g_return_if_fail (GLADE_IS_BASE_EDITOR (editor)); + + if (val) + gtk_widget_show (editor->priv->signal_editor_w); + else + gtk_widget_hide (editor->priv->signal_editor_w); +} + +/* Convenience functions */ + +static void +glade_base_editor_help (GtkButton *button, gchar *markup) +{ + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (glade_app_get_transient_parent (), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, " "); + + gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), markup); + + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); +} + +/** + * glade_base_editor_pack_new_window: + * @editor: a #GladeBaseEditor + * @title: the window title + * @help_markup: the help text + * + * This convenience function create a new modal window and packs @editor in it. + * Returns the newly created window + */ +GtkWidget * +glade_base_editor_pack_new_window (GladeBaseEditor *editor, + gchar *title, + gchar *help_markup) +{ + GtkWidget *window, *buttonbox, *button; + gchar *real_title; + + g_return_val_if_fail (GLADE_IS_BASE_EDITOR (editor), NULL); + + /* Window */ + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_modal (GTK_WINDOW (window), TRUE); + gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DIALOG); + + if (title) + { + real_title = g_strdup_printf ("%s - %s", title, + glade_widget_get_name (editor->priv->gcontainer)); + gtk_window_set_title (GTK_WINDOW (window), real_title); + g_free (real_title); + } + + /* Button Box */ + buttonbox = gtk_hbutton_box_new (); + gtk_widget_show (buttonbox); + gtk_button_box_set_layout (GTK_BUTTON_BOX (buttonbox), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX (buttonbox), 8); + gtk_box_pack_start (GTK_BOX (editor), buttonbox, FALSE, TRUE, 0); + + button = glade_app_undo_button_new (); + gtk_widget_show (button); + gtk_container_add (GTK_CONTAINER (buttonbox), button); + + button = glade_app_redo_button_new (); + gtk_widget_show (button); + gtk_container_add (GTK_CONTAINER (buttonbox), button); + + button = gtk_button_new_from_stock (GTK_STOCK_CLOSE); + gtk_widget_show (button); + g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window); + gtk_container_add (GTK_CONTAINER (buttonbox), button); + + if (help_markup) + { + button = gtk_button_new_from_stock (GTK_STOCK_HELP); + gtk_widget_show (button); + g_signal_connect (button, "clicked", + G_CALLBACK (glade_base_editor_help), + help_markup); + gtk_container_add (GTK_CONTAINER (buttonbox), button); + gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (buttonbox), button, TRUE); + } + + gtk_container_set_border_width (GTK_CONTAINER (editor), GLADE_GENERIC_BORDER_WIDTH); + gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor)); + + gtk_window_set_default_size (GTK_WINDOW (window), 640, 480); + + return window; +} diff --git a/src/glade-base-editor.h b/src/glade-base-editor.h new file mode 100644 index 00000000..8d0ce7ee --- /dev/null +++ b/src/glade-base-editor.h @@ -0,0 +1,100 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2006 Juan Pablo Ugarte. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Authors: + * Juan Pablo Ugarte <juanpablougarte@gmail.com> + */ +#ifndef __GLADE_BASE_EDITOR_H__ +#define __GLADE_BASE_EDITOR_H__ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "glade-widget.h" +#include "glade-marshallers.h" +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define GLADE_TYPE_BASE_EDITOR (glade_base_editor_get_type ()) +#define GLADE_BASE_EDITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GLADE_TYPE_BASE_EDITOR, GladeBaseEditor)) +#define GLADE_BASE_EDITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GLADE_TYPE_BASE_EDITOR, GladeBaseEditorClass)) +#define GLADE_IS_BASE_EDITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GLADE_TYPE_BASE_EDITOR)) +#define GLADE_IS_BASE_EDITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GLADE_TYPE_BASE_EDITOR)) +#define GLADE_BASE_EDITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GLADE_TYPE_BASE_EDITOR, GladeBaseEditorClass)) + +typedef struct _GladeBaseEditor GladeBaseEditor; +typedef struct _GladeBaseEditorPrivate GladeBaseEditorPrivate; +typedef struct _GladeBaseEditorClass GladeBaseEditorClass; + +struct _GladeBaseEditor +{ + GtkVBox parent; + GladeBaseEditorPrivate *priv; +}; + +struct _GladeBaseEditorClass +{ + GtkVBoxClass parent_class; + void (*child_selected) (GladeBaseEditor *, GladeWidget *); + gboolean (*change_type) (GladeBaseEditor *, GladeWidget *, GType); + gchar * (*get_display_name) (GladeBaseEditor *, GladeWidget *); + GladeWidget * (*build_child) (GladeBaseEditor *, GladeWidget *, GType); + gboolean (*delete_child) (GladeBaseEditor *, GladeWidget *, GladeWidget *); + gboolean (*move_child) (GladeBaseEditor *, GladeWidget *, GladeWidget *); +}; + +LIBGLADEUI_API +GType glade_base_editor_get_type (void); + +LIBGLADEUI_API +GladeBaseEditor *glade_base_editor_new (GObject *container, + gboolean tree_like, + ...); + +LIBGLADEUI_API +void glade_base_editor_add_default_properties (GladeBaseEditor *editor, + GladeWidget *gchild); + +LIBGLADEUI_API +void glade_base_editor_add_properties (GladeBaseEditor *editor, + GladeWidget *gchild, + ...); + +LIBGLADEUI_API +void glade_base_editor_add_label (GladeBaseEditor *editor, + gchar *str); + +LIBGLADEUI_API +void glade_base_editor_add_popup_items (GladeBaseEditor *editor, + ...); + +LIBGLADEUI_API +void glade_base_editor_set_show_signal_editor (GladeBaseEditor *editor, + gboolean val); + +/* Convenience functions */ +LIBGLADEUI_API +GtkWidget *glade_base_editor_pack_new_window (GladeBaseEditor *editor, + gchar *title, + gchar *markup); + +G_END_DECLS + +#endif /* __GLADE_BASE_EDITOR_H__ */ diff --git a/src/glade-command.c b/src/glade-command.c index e09c2b38..39d885e3 100644 --- a/src/glade-command.c +++ b/src/glade-command.c @@ -1138,7 +1138,7 @@ glade_command_create (GladeWidgetClass *class, g_return_val_if_fail (class != NULL, NULL); g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL); - if (g_type_is_a (class->type, GTK_TYPE_WINDOW) == FALSE) + if (class->toplevel == FALSE) g_return_val_if_fail (GLADE_IS_WIDGET (parent), NULL); me = g_object_new (GLADE_COMMAND_CREATE_DELETE_TYPE, NULL); diff --git a/src/glade-editor-property.c b/src/glade-editor-property.c index eb49cbe7..c81609a4 100644 --- a/src/glade-editor-property.c +++ b/src/glade-editor-property.c @@ -185,6 +185,7 @@ glade_editor_property_sensitivity_cb (GladeProperty *property, void glade_editor_property_value_changed_cb (GladeProperty *property, + GValue *old_value, GValue *value, GladeEditorProperty *eprop) { diff --git a/src/glade-gtk.c b/src/glade-gtk.c index db0134bc..2287636b 100644 --- a/src/glade-gtk.c +++ b/src/glade-gtk.c @@ -25,6 +25,7 @@ #include "glade-gtk.h" #include "glade-editor-property.h" +#include "glade-base-editor.h" #include "fixed_bg.xpm" @@ -2910,6 +2911,7 @@ glade_gtk_image_restore_stock (GladeWidget *gwidget) static void glade_gtk_image_pixel_size_changed (GladeProperty *property, + GValue *old_value, GValue *value, GladeWidget *gimage) { @@ -3195,6 +3197,215 @@ glade_gtk_menu_shell_set_child_property (GObject *container, property_name, value); } +static gchar * +glade_gtk_menu_shell_get_display_name (GladeBaseEditor *editor, + GladeWidget *gchild, + gpointer user_data) +{ + GObject *child = glade_widget_get_object (gchild); + gchar *name; + + if (GTK_IS_SEPARATOR_MENU_ITEM (child)) + name = _("<separator>"); + else + glade_widget_property_get (gchild, "label", &name); + + return g_strdup (name); +} + +static GladeWidget * +glade_gtk_menu_shell_item_get_parent (GladeWidget *gparent, GObject *parent) +{ + GtkWidget *submenu; + + if ((submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (parent)))) + gparent = glade_widget_get_from_gobject (submenu); + else + gparent = glade_command_create (glade_widget_class_get_by_type (GTK_TYPE_MENU), + gparent, NULL, glade_widget_get_project (gparent)); + return gparent; +} + +static GladeWidget * +glade_gtk_menu_shell_build_child (GladeBaseEditor *editor, + GladeWidget *gparent, + GType type, + gpointer data) +{ + GObject *parent = glade_widget_get_object (gparent); + GladeWidget *gitem_new; + + if (GTK_IS_SEPARATOR_MENU_ITEM (parent)) + return NULL; + + /* Get or build real parent */ + if (GTK_IS_MENU_ITEM (parent)) + gparent = glade_gtk_menu_shell_item_get_parent (gparent, parent); + + /* Build child */ + gitem_new = glade_command_create (glade_widget_class_get_by_type (type), + gparent, NULL, + glade_widget_get_project (gparent)); + + if (type != GTK_TYPE_SEPARATOR_MENU_ITEM) + { + glade_widget_property_set (gitem_new, "label", + glade_widget_get_name (gitem_new)); + glade_widget_property_set (gitem_new, "use-underline", TRUE); + } + + return gitem_new; +} + +static GladeWidget * +glade_gtk_menu_shell_delete_child (GladeBaseEditor *editor, + GladeWidget *gparent, + GladeWidget *gchild, + gpointer data) +{ + GObject *item = glade_widget_get_object (gparent); + GtkWidget *submenu; + GList list = {0, }; + gint n_children; + + if ((submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (item)))) + { + GList *l = gtk_container_get_children (GTK_CONTAINER (submenu)); + n_children = g_list_length (l); + g_list_free (l); + } + + if (submenu && n_children == 1) + list.data = glade_widget_get_parent (gchild); + else + list.data = gchild; + + /* Remove widget */ + glade_command_delete (&list); + + return TRUE; +} + +static gboolean +glade_gtk_menu_shell_move_child (GladeBaseEditor *editor, + GladeWidget *gparent, + GladeWidget *gchild, + gpointer data) +{ + GObject *parent = glade_widget_get_object (gparent); + GList list = {0, }; + + if (GTK_IS_SEPARATOR_MENU_ITEM (parent)) return FALSE; + + if (GTK_IS_MENU_ITEM (parent)) + gparent = glade_gtk_menu_shell_item_get_parent (gparent, parent); + + list.data = gchild; + glade_command_cut (&list); + glade_command_paste (&list, gparent, NULL); + + return TRUE; +} + +static gboolean +glade_gtk_menu_shell_change_type (GladeBaseEditor *editor, + GladeWidget *gchild, + GType type, + gpointer data) +{ + GObject *child = glade_widget_get_object (gchild); + + if (type == GTK_TYPE_SEPARATOR_MENU_ITEM && + gtk_menu_item_get_submenu (GTK_MENU_ITEM (child))) + return TRUE; + + return FALSE; +} + +static void +glade_gtk_menu_shell_child_selected (GladeBaseEditor *editor, + GladeWidget *gchild, + gpointer data) +{ + GObject *child = glade_widget_get_object (gchild); + GType type = G_OBJECT_TYPE (child); + + glade_base_editor_add_label (editor, "Menu Item"); + + glade_base_editor_add_default_properties (editor, gchild); + + if (GTK_IS_SEPARATOR_MENU_ITEM (child)) return; + + glade_base_editor_add_label (editor, "Properties"); + + glade_base_editor_add_properties (editor, gchild, "label", "tooltip", NULL); + + if (type == GTK_TYPE_IMAGE_MENU_ITEM) + { + GtkWidget *image; + GladeWidget *internal; + + glade_base_editor_add_properties (editor, gchild, "stock", NULL); + + if ((image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (child)))) + { + if ((internal = glade_widget_get_from_gobject (image)) && + internal->internal) + { + glade_base_editor_add_label (editor, "Internal Image Properties"); + glade_base_editor_add_properties (editor, internal, "glade-type", "pixbuf", "glade-stock", "icon-name", NULL); + } + } + } + else + if (type == GTK_TYPE_CHECK_MENU_ITEM) + glade_base_editor_add_properties (editor, gchild, + "active", "draw-as-radio", + "inconsistent", NULL); + else + if (type == GTK_TYPE_RADIO_MENU_ITEM) + glade_base_editor_add_properties (editor, gchild, + "active", "group", NULL); +} + +static void +glade_gtk_menu_shell_launch_editor (GObject *object, gchar *title) +{ + GladeBaseEditor *editor; + GtkWidget *window; + + /* Editor */ + editor = glade_base_editor_new (object, TRUE, + _("Normal"), GTK_TYPE_MENU_ITEM, + _("Image"), GTK_TYPE_IMAGE_MENU_ITEM, + _("Check"), GTK_TYPE_CHECK_MENU_ITEM, + _("Radio"), GTK_TYPE_RADIO_MENU_ITEM, + _("Separator"), GTK_TYPE_SEPARATOR_MENU_ITEM, + NULL); + + glade_base_editor_add_popup_items (editor, + _("Add Item"), GTK_TYPE_MENU_ITEM, FALSE, + _("Add Child Item"), GTK_TYPE_MENU_ITEM, TRUE, + _("Add Separator"), GTK_TYPE_SEPARATOR_MENU_ITEM, FALSE, + NULL); + + g_signal_connect (editor, "get-display-name", G_CALLBACK (glade_gtk_menu_shell_get_display_name), NULL); + g_signal_connect (editor, "child-selected", G_CALLBACK (glade_gtk_menu_shell_child_selected), NULL); + g_signal_connect (editor, "change-type", G_CALLBACK (glade_gtk_menu_shell_change_type), NULL); + g_signal_connect (editor, "build-child", G_CALLBACK (glade_gtk_menu_shell_build_child), NULL); + g_signal_connect (editor, "delete-child", G_CALLBACK (glade_gtk_menu_shell_delete_child), NULL); + g_signal_connect (editor, "move-child", G_CALLBACK (glade_gtk_menu_shell_move_child), NULL); + + gtk_widget_show (GTK_WIDGET (editor)); + + window = glade_base_editor_pack_new_window (editor, title, + _("<big><b>Tips:</b></big>\n" + " * Right click over the treeview to add items.\n" + " * Press Delete to remove the selected item.\n" + " * Drag & Drop to reorder.\n" + " * Type column is editable.")); + gtk_widget_show (window); +} /* ----------------------------- GtkMenuItem(s) ------------------------------ */ GList * GLADEGTK_API @@ -3631,38 +3842,49 @@ glade_gtk_menu_bar_append_new_item (GladeWidget *parent, const gchar *label, gboolean use_stock) { - static GladeWidgetClass *item_class = NULL, *image_item_class; + static GladeWidgetClass *item_class = NULL, *image_item_class, *separator_class; GladeWidget *gitem; if (item_class == NULL) { item_class = glade_widget_class_get_by_type (GTK_TYPE_MENU_ITEM); image_item_class = glade_widget_class_get_by_type (GTK_TYPE_IMAGE_MENU_ITEM); + separator_class = glade_widget_class_get_by_type (GTK_TYPE_SEPARATOR_MENU_ITEM); } - - gitem = glade_widget_class_create_widget ((use_stock) ? image_item_class : item_class, - FALSE, "parent", parent, - "project", project, - NULL); - glade_widget_property_set (gitem, "use-underline", TRUE); - - if (use_stock) + if (label) { - GEnumClass *eclass; - GEnumValue *eval; + gitem = glade_widget_class_create_widget ((use_stock) ? image_item_class : item_class, + FALSE, "parent", parent, + "project", project, + NULL); + + glade_widget_property_set (gitem, "use-underline", TRUE); + + if (use_stock) + { + GEnumClass *eclass; + GEnumValue *eval; - eclass = g_type_class_ref (GLADE_TYPE_STOCK); - eval = g_enum_get_value_by_nick (eclass, label); + eclass = g_type_class_ref (GLADE_TYPE_STOCK); + eval = g_enum_get_value_by_nick (eclass, label); - if (eval) - glade_widget_property_set (gitem, "stock", eval->value); + if (eval) + glade_widget_property_set (gitem, "stock", eval->value); - g_type_class_unref (eclass); + g_type_class_unref (eclass); + } + else + { + glade_widget_property_set (gitem, "label", label); + } } else { - glade_widget_property_set (gitem, "label", label); + gitem = glade_widget_class_create_widget (separator_class, + FALSE, "parent", parent, + "project", project, + NULL); } glade_widget_add_child (parent, gitem, FALSE); @@ -3687,1379 +3909,43 @@ glade_gtk_menu_bar_post_create (GObject *object, GladeCreateReason reason) /* File */ gitem = glade_gtk_menu_bar_append_new_item (gmenubar, project, _("_File"), FALSE); gsubmenu = glade_gtk_menu_bar_append_new_submenu (gitem, project); + glade_gtk_menu_bar_append_new_item (gsubmenu, project, "gtk-new", TRUE); + glade_gtk_menu_bar_append_new_item (gsubmenu, project, "gtk-open", TRUE); + glade_gtk_menu_bar_append_new_item (gsubmenu, project, "gtk-save", TRUE); + glade_gtk_menu_bar_append_new_item (gsubmenu, project, "gtk-save-as", TRUE); + glade_gtk_menu_bar_append_new_item (gsubmenu, project, NULL, FALSE); glade_gtk_menu_bar_append_new_item (gsubmenu, project, "gtk-quit", TRUE); + /* Edit */ + gitem = glade_gtk_menu_bar_append_new_item (gmenubar, project, _("_Edit"), FALSE); + gsubmenu = glade_gtk_menu_bar_append_new_submenu (gitem, project); + glade_gtk_menu_bar_append_new_item (gsubmenu, project, "gtk-cut", TRUE); + glade_gtk_menu_bar_append_new_item (gsubmenu, project, "gtk-copy", TRUE); + glade_gtk_menu_bar_append_new_item (gsubmenu, project, "gtk-paste", TRUE); + glade_gtk_menu_bar_append_new_item (gsubmenu, project, "gtk-delete", TRUE); + + /* View */ + gitem = glade_gtk_menu_bar_append_new_item (gmenubar, project, _("_View"), FALSE); + /* Help */ gitem = glade_gtk_menu_bar_append_new_item (gmenubar, project, _("_Help"), FALSE); gsubmenu = glade_gtk_menu_bar_append_new_submenu (gitem, project); glade_gtk_menu_bar_append_new_item (gsubmenu, project, "gtk-about", TRUE); } - -/* ----------------------------- GtkMenu Editor ------------------------------ */ -typedef enum -{ - GLADEGTK_MENU_GWIDGET, - GLADEGTK_MENU_OBJECT, - GLADEGTK_MENU_TYPE_NAME, - GLADEGTK_MENU_LABEL, - GLADEGTK_MENU_TOOLTIP, - GLADEGTK_MENU_N_COLUMNS -}GladeGtkMenuEditorEnum; - -typedef struct _GladeGtkMenuEditor GladeGtkMenuEditor; - -#define MENU_EDITOR_SEPARATOR_LABEL "<separator>" - -struct _GladeGtkMenuEditor -{ - GtkWidget *window, *popup, *table, *child_table, *treeview; - GtkWidget *remove_button, *undo_button, *redo_button; - GtkTreeStore *store; - GladeWidget *gmenubar; - GladeSignalEditor *signal_editor; - GladeProject *project; - - /* Temporal variables used in idle functions */ - GtkTreeIter iter; -}; - -static const gchar * -glade_gtk_menu_editor_type_name (GType type) -{ - - if (type == GTK_TYPE_MENU_ITEM) - return _("Normal"); - - if (type == GTK_TYPE_IMAGE_MENU_ITEM) - return _("Image"); - - if (type == GTK_TYPE_CHECK_MENU_ITEM) - return _("Check"); - - if (type == GTK_TYPE_RADIO_MENU_ITEM) - return _("Radio"); - - if (type == GTK_TYPE_SEPARATOR_MENU_ITEM) - return _("Separator"); - - return ""; -} - -static void -glade_gtk_menu_editor_fill_store (GtkWidget *widget, - GtkTreeStore *tree_store, - GtkTreeIter *parent) -{ - GList *menu_items = (GTK_MENU_SHELL(widget))->children; - - while(menu_items) - { - GtkTreeIter iter; - GtkWidget *submenu; - GtkWidget *menu_item = GTK_WIDGET (((GtkMenuItem *)menu_items->data)); - - if(menu_item) - { - GladeWidget *gitem; - GObject *item; - gchar *label, *tooltip; - - item = G_OBJECT (menu_item); - gitem = glade_widget_get_from_gobject (item); - - gtk_tree_store_append (tree_store, &iter, parent); - - if (GTK_IS_SEPARATOR_MENU_ITEM (item)) - { - gtk_tree_store_set (tree_store, &iter, - GLADEGTK_MENU_GWIDGET, gitem, - GLADEGTK_MENU_OBJECT, item, - GLADEGTK_MENU_TYPE_NAME, glade_gtk_menu_editor_type_name (G_OBJECT_TYPE (item)), - GLADEGTK_MENU_LABEL, MENU_EDITOR_SEPARATOR_LABEL, - GLADEGTK_MENU_TOOLTIP, NULL, - -1); - } - else - { - glade_widget_property_get (gitem, "label", &label); - glade_widget_property_get (gitem, "tooltip", &tooltip); - - gtk_tree_store_set (tree_store, &iter, - GLADEGTK_MENU_GWIDGET, gitem, - GLADEGTK_MENU_OBJECT, item, - GLADEGTK_MENU_TYPE_NAME, glade_gtk_menu_editor_type_name (G_OBJECT_TYPE (item)), - GLADEGTK_MENU_LABEL, label, - GLADEGTK_MENU_TOOLTIP, tooltip, - -1); - } - } - - submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item)); - if (submenu) glade_gtk_menu_editor_fill_store (submenu, tree_store, &iter); - - menu_items = g_list_next (menu_items); - } -} - -typedef enum -{ - GLADEGTK_MENU_ITEM_CLASS, - GLADEGTK_MENU_ITEM_NAME, - GLADEGTK_MENU_ITEM_N_COLUMNS -}GladeGtkMenuItemEnum; - -static -GtkTreeModel * -glade_gtk_menu_editor_get_item_model () -{ - static GtkListStore *store = NULL; - - if (store == NULL) - { - GtkTreeIter iter; - - store = gtk_list_store_new (GLADEGTK_MENU_ITEM_N_COLUMNS, - G_TYPE_POINTER, - G_TYPE_STRING); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - GLADEGTK_MENU_ITEM_CLASS, glade_widget_class_get_by_type (GTK_TYPE_MENU_ITEM), - GLADEGTK_MENU_ITEM_NAME, glade_gtk_menu_editor_type_name (GTK_TYPE_MENU_ITEM), - -1); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - GLADEGTK_MENU_ITEM_CLASS, glade_widget_class_get_by_type (GTK_TYPE_IMAGE_MENU_ITEM), - GLADEGTK_MENU_ITEM_NAME, glade_gtk_menu_editor_type_name (GTK_TYPE_IMAGE_MENU_ITEM), - -1); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - GLADEGTK_MENU_ITEM_CLASS, glade_widget_class_get_by_type (GTK_TYPE_CHECK_MENU_ITEM), - GLADEGTK_MENU_ITEM_NAME, glade_gtk_menu_editor_type_name (GTK_TYPE_CHECK_MENU_ITEM), - -1); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - GLADEGTK_MENU_ITEM_CLASS, glade_widget_class_get_by_type (GTK_TYPE_RADIO_MENU_ITEM), - GLADEGTK_MENU_ITEM_NAME, glade_gtk_menu_editor_type_name (GTK_TYPE_RADIO_MENU_ITEM), - -1); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - GLADEGTK_MENU_ITEM_CLASS, glade_widget_class_get_by_type (GTK_TYPE_SEPARATOR_MENU_ITEM), - GLADEGTK_MENU_ITEM_NAME, glade_gtk_menu_editor_type_name (GTK_TYPE_SEPARATOR_MENU_ITEM), - -1); - } - - return GTK_TREE_MODEL (store); -} - -static gboolean -glade_gtk_menu_editor_get_item_selected (GladeGtkMenuEditor *e, GtkTreeIter *iter) -{ - GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (e->treeview)); - return gtk_tree_selection_get_selected (sel, NULL, iter); -} - -static void -glade_gtk_menu_editor_string_value_changed (GladeGtkMenuEditor *e, GValue *value, gint column) -{ - GtkTreeIter iter; - const gchar *text; - - if (glade_gtk_menu_editor_get_item_selected (e, &iter)) - { - text = g_value_get_string (value); - gtk_tree_store_set (e->store, &iter, column, text, -1); - } -} - -static void -glade_gtk_menu_editor_label_changed (GladeProperty *property, - GValue *value, - GladeGtkMenuEditor *e) -{ - glade_gtk_menu_editor_string_value_changed (e, value, GLADEGTK_MENU_LABEL); -} - -static void -glade_gtk_menu_editor_tooltip_changed (GladeProperty *property, - GValue *value, - GladeGtkMenuEditor *e) -{ - glade_gtk_menu_editor_string_value_changed (e, value, GLADEGTK_MENU_TOOLTIP); -} - -static void -glade_gtk_menu_editor_name_activate (GtkEntry *entry, GladeWidget *gitem) -{ - const gchar *text = gtk_entry_get_text (GTK_ENTRY (entry)); - - if (strcmp (glade_widget_get_name (gitem), text)) - glade_command_set_name (gitem, text); -} - -static gboolean -glade_gtk_menu_editor_name_focus_out (GtkWidget *entry, - GdkEventFocus *event, - GladeWidget *gitem) -{ - glade_gtk_menu_editor_name_activate (GTK_ENTRY (entry), gitem); - return FALSE; -} - -static void -glade_gtk_menu_editor_item_change_type (GladeGtkMenuEditor *e, - GtkTreeIter *iter, - GladeWidgetClass *klass, - const gchar *klass_name); - -static void -glade_gtk_menu_editor_type_changed (GtkComboBox *widget, GladeGtkMenuEditor *e) -{ - GtkTreeIter iter, combo_iter; - GladeWidgetClass *klass; - gchar *klass_name; - - if (! glade_gtk_menu_editor_get_item_selected (e, &iter)) - return; - - gtk_combo_box_get_active_iter (widget, &combo_iter); - - gtk_tree_model_get (gtk_combo_box_get_model (widget), &combo_iter, - GLADEGTK_MENU_ITEM_CLASS, &klass, - GLADEGTK_MENU_ITEM_NAME, &klass_name, -1); - - glade_gtk_menu_editor_item_change_type (e, &iter, klass, klass_name); - - g_free (klass_name); -} - -static void -glade_gtk_menu_editor_remove_widget (GtkWidget *widget, gpointer container) -{ - gtk_container_remove (GTK_CONTAINER (container), widget); -} - -static void -glade_gtk_menu_editor_table_attach (GtkWidget *table, - GtkWidget *child1, - GtkWidget *child2, - gint *row_ptr) -{ - gint row = *row_ptr; - - if (child1) - { - gtk_table_attach (GTK_TABLE (table), child1, 0, 1, row, row + 1, - GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0); - gtk_widget_show (child1); - } - - if (child2) - { - gtk_table_attach (GTK_TABLE (table), child2, 1, 2, row, row + 1, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0); - gtk_widget_show (child2); - } - - (*row_ptr)++; -} - -static void -glade_gtk_menu_editor_treeview_fill_child_table (GladeGtkMenuEditor *e, GladeWidget *internal) -{ - GtkWidget *label, *table; - GtkWidget *eprop; - gint row = 1; - - table = e->child_table; - - label = gtk_label_new (NULL); - gtk_label_set_markup (GTK_LABEL (label), _("<span rise=\"-20000\"><b>Internal Image Properties</b></span>")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_widget_show (label); - gtk_table_attach (GTK_TABLE (table), label, 0, 2, 0, 1, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0); - - eprop = (GtkWidget *)glade_editor_property_new_from_widget - (internal, "glade-type", TRUE); - if (eprop) - glade_gtk_menu_editor_table_attach (table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); - - eprop = (GtkWidget *)glade_editor_property_new_from_widget (internal, "pixbuf", TRUE); - if (eprop) - glade_gtk_menu_editor_table_attach (table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); - - eprop = (GtkWidget *)glade_editor_property_new_from_widget (internal, "glade-stock", TRUE); - if (eprop) - glade_gtk_menu_editor_table_attach (table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); - - eprop = (GtkWidget *)glade_editor_property_new_from_widget (internal, "icon-name", TRUE); - if (eprop) - glade_gtk_menu_editor_table_attach (table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); -} - -static void -glade_gtk_menu_editor_use_stock_changed (GladeProperty *property, - GValue *value, - GladeGtkMenuEditor *e) -{ - GtkTreeIter iter; - GtkWidget *image; - GObject *item; - GladeWidget *internal; - - gtk_container_foreach (GTK_CONTAINER (e->child_table), - glade_gtk_menu_editor_remove_widget, e->child_table); - - if (! glade_gtk_menu_editor_get_item_selected (e, &iter)) - return; - - gtk_tree_model_get (GTK_TREE_MODEL (e->store), &iter, - GLADEGTK_MENU_OBJECT, &item, -1); - - if ((image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (item)))) - { - if ((internal = glade_widget_get_from_gobject (image))) - if (internal->internal) - glade_gtk_menu_editor_treeview_fill_child_table (e, internal); - } -} - -static void -glade_gtk_menu_editor_eprop_destroyed (GtkWidget *object, gpointer data) -{ - /* This will disconnect signals attatched to the property by the menu-editor */ - g_signal_handlers_disconnect_matched (GLADE_EDITOR_PROPERTY (object)->property, - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, data); -} - -static void -glade_gtk_menu_editor_clear (GladeGtkMenuEditor *e) -{ - gtk_container_foreach (GTK_CONTAINER (e->table), - glade_gtk_menu_editor_remove_widget, e->table); - gtk_container_foreach (GTK_CONTAINER (e->child_table), - glade_gtk_menu_editor_remove_widget, e->child_table); - - gtk_widget_set_sensitive (e->remove_button, FALSE); - glade_signal_editor_load_widget (e->signal_editor, NULL); -} - -static void -glade_gtk_menu_editor_treeview_cursor_changed (GtkTreeView *treeview, - GladeGtkMenuEditor *e) -{ - GtkTreeIter iter, combo_iter; - GtkWidget *label, *entry; - GtkTreeModel *item_class; - GtkCellRenderer *renderer; - GObject *item; - GladeWidgetClass *item_klass, *klass; - GtkWidget *eprop; - GladeWidget *gitem; - gint row = 0; - GladeProperty *property; - - if (! glade_gtk_menu_editor_get_item_selected (e, &iter)) - return; - - glade_gtk_menu_editor_clear (e); - gtk_widget_set_sensitive (e->remove_button, TRUE); - - gtk_tree_model_get (GTK_TREE_MODEL (e->store), &iter, - GLADEGTK_MENU_GWIDGET, &gitem, - GLADEGTK_MENU_OBJECT, &item, -1); - - /* Name */ - label = gtk_label_new (_("Name :")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.0); - - entry = gtk_entry_new (); - gtk_entry_set_text (GTK_ENTRY (entry), glade_widget_get_name (gitem)); - g_signal_connect (entry, "activate", G_CALLBACK (glade_gtk_menu_editor_name_activate), gitem); - g_signal_connect (entry, "focus-out-event", G_CALLBACK (glade_gtk_menu_editor_name_focus_out), gitem); - glade_gtk_menu_editor_table_attach (e->table, label, entry, &row); - - /* Type */ - label = gtk_label_new (_("Type :")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.0); - - entry = gtk_combo_box_new (); - item_class = glade_gtk_menu_editor_get_item_model (); - gtk_combo_box_set_model (GTK_COMBO_BOX (entry), item_class); - - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(entry), renderer, FALSE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT(entry), renderer, "text", - GLADEGTK_MENU_ITEM_NAME, NULL); - - item_klass = glade_widget_class_get_by_type (G_OBJECT_TYPE (item)); - gtk_tree_model_get_iter_first (item_class, &combo_iter); - do - { - gtk_tree_model_get (item_class, &combo_iter, - GLADEGTK_MENU_ITEM_CLASS, &klass, -1); - if (item_klass == klass) - { - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (entry), - &combo_iter); - break; - } - - } while (gtk_tree_model_iter_next (item_class, &combo_iter)); - - g_signal_connect (entry, "changed", G_CALLBACK (glade_gtk_menu_editor_type_changed), e); - glade_gtk_menu_editor_table_attach (e->table, label, entry, &row); - - label = gtk_label_new (NULL); - gtk_label_set_markup (GTK_LABEL (label), _("<span rise=\"-20000\"><b>Properties</b></span>")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); - glade_gtk_menu_editor_table_attach (e->table, label, NULL, &row); - - if (! GTK_IS_SEPARATOR_MENU_ITEM (item)) - { - /* Label */ - eprop = (GtkWidget *)glade_editor_property_new_from_widget (gitem, "label", TRUE); - if (eprop) - { - glade_gtk_menu_editor_table_attach - (e->table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); - g_signal_connect (GLADE_EDITOR_PROPERTY (eprop)->property, "value-changed", - G_CALLBACK (glade_gtk_menu_editor_label_changed), e); - g_signal_connect (eprop, "destroy", - G_CALLBACK (glade_gtk_menu_editor_eprop_destroyed), e); - } - - /* Tooltip */ - eprop = (GtkWidget *)glade_editor_property_new_from_widget (gitem, "tooltip", TRUE); - if (eprop) - { - glade_gtk_menu_editor_table_attach - (e->table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); - g_signal_connect (GLADE_EDITOR_PROPERTY (eprop)->property, "value-changed", - G_CALLBACK (glade_gtk_menu_editor_tooltip_changed), e); - g_signal_connect (eprop, "destroy", - G_CALLBACK (glade_gtk_menu_editor_eprop_destroyed), e); - } - } - - if (GTK_IS_IMAGE_MENU_ITEM (item)) - { - eprop = (GtkWidget *)glade_editor_property_new_from_widget (gitem, "stock", TRUE); - if (eprop) - glade_gtk_menu_editor_table_attach - (e->table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); - - property = glade_widget_get_property (gitem, "use-stock"); - g_signal_connect (property, "value-changed", - G_CALLBACK (glade_gtk_menu_editor_use_stock_changed), e); - - /* Internal child properties */ - glade_gtk_menu_editor_use_stock_changed (NULL, NULL, e); - } - - if (GTK_IS_CHECK_MENU_ITEM (item)) - { - eprop = (GtkWidget *)glade_editor_property_new_from_widget (gitem, "active", TRUE); - if (eprop) - glade_gtk_menu_editor_table_attach - (e->table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); - - if (GTK_IS_RADIO_MENU_ITEM (item)) - { - eprop = (GtkWidget *)glade_editor_property_new_from_widget (gitem, "group", TRUE); - if (eprop) - glade_gtk_menu_editor_table_attach - (e->table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); - } - else - { - eprop = (GtkWidget *)glade_editor_property_new_from_widget - (gitem, "draw-as-radio", TRUE); - if (eprop) - glade_gtk_menu_editor_table_attach - (e->table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); - - eprop = (GtkWidget *)glade_editor_property_new_from_widget - (gitem, "inconsistent", TRUE); - if (eprop) - glade_gtk_menu_editor_table_attach - (e->table, GLADE_EDITOR_PROPERTY (eprop)->eventbox, eprop, &row); - } - } - - /* Update Signal Editor*/ - glade_signal_editor_load_widget (e->signal_editor, gitem); -} - - -static void -glade_gtk_menu_editor_reorder_children (GtkWidget *menushell, - GtkTreeModel *model, - GtkTreeIter *child) -{ - GladeWidget *gitem; - GladeProperty *property; - GtkTreeIter parent, iter; - GValue val = {0, }; - gint position = 0; - - if (gtk_tree_model_iter_parent (model, &parent, child)) - gtk_tree_model_iter_children (model, &iter, &parent); - else - gtk_tree_model_get_iter_first (model, &iter); - - g_value_init (&val, G_TYPE_INT); - - do - { - gtk_tree_model_get (model, &iter, GLADEGTK_MENU_GWIDGET, &gitem, -1); - g_value_set_int (&val, position++); - - if ((property = glade_widget_get_property (gitem, "position")) != NULL) - glade_command_set_property (property, &val); - } while (gtk_tree_model_iter_next (model, &iter)); -} - -static void -glade_gtk_menu_editor_set_cursor (GladeGtkMenuEditor *e, GtkTreeIter *iter) -{ - GtkTreePath *path; - - if ((path = gtk_tree_model_get_path (GTK_TREE_MODEL (e->store), iter))) - { - gtk_tree_view_set_cursor (GTK_TREE_VIEW (e->treeview), path, NULL, FALSE); - gtk_tree_path_free (path); - } -} - -static gboolean -glade_gtk_menu_editor_find_child_real (GladeGtkMenuEditor *e, - GladeWidget *child, - GtkTreeIter *iter) -{ - GtkTreeModel *model = GTK_TREE_MODEL (e->store); - GtkTreeIter child_iter; - GladeWidget *item; - - do - { - gtk_tree_model_get (model, iter, GLADEGTK_MENU_GWIDGET, &item, -1); - - if (item == child) return TRUE; - - if (gtk_tree_model_iter_children (model, &child_iter, iter)) - if (glade_gtk_menu_editor_find_child_real (e, child, &child_iter)) - { - *iter = child_iter; - return TRUE; - } - } - while (gtk_tree_model_iter_next (model, iter)); - - return FALSE; -} - -static gboolean -glade_gtk_menu_editor_find_child (GladeGtkMenuEditor *e, - GladeWidget *child, - GtkTreeIter *iter) -{ - if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (e->store), iter)) - return glade_gtk_menu_editor_find_child_real (e, child, iter); - - return FALSE; -} - -static void -glade_gtk_menu_editor_select_child (GladeGtkMenuEditor *e, - GladeWidget *child) -{ - GtkTreeIter iter; - - if (glade_gtk_menu_editor_find_child (e, child, &iter)) - glade_gtk_menu_editor_set_cursor (e, &iter); -} - -static void -glade_gtk_menu_editor_block_callbacks (GladeGtkMenuEditor *e, gboolean block); - -static void -glade_gtk_menu_editor_item_change_type (GladeGtkMenuEditor *e, - GtkTreeIter *iter, - GladeWidgetClass *klass, - const gchar *klass_name) -{ - GladeWidget *parent, *gitem, *gitem_new; - GObject *item, *item_new; - gchar *name, *label, *tooltip, *desc; - GtkWidget *submenu; - GList list = {0, }; - - glade_gtk_menu_editor_block_callbacks (e, TRUE); - - /* Get old widget data */ - gtk_tree_model_get (GTK_TREE_MODEL (e->store), iter, - GLADEGTK_MENU_GWIDGET, &gitem, - GLADEGTK_MENU_OBJECT, &item, - GLADEGTK_MENU_LABEL, &label, - GLADEGTK_MENU_TOOLTIP, &tooltip, - -1); - parent = glade_widget_get_parent (gitem); - name = g_strdup (glade_widget_get_name (gitem)); - submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (item)); - - /* Start of glade-command */ - desc = g_strdup_printf (_("Setting menu item type on %s to %s"), - name, klass_name); - glade_command_push_group (desc); - g_free (desc); - - /* Create new widget */ - gitem_new = glade_command_create (klass, parent, NULL, e->project); - item_new = glade_widget_get_object (gitem_new); - glade_widget_set_name (gitem_new, name); - - if (GTK_IS_SEPARATOR_MENU_ITEM (item_new)) - { - gtk_tree_store_set (e->store, iter, - GLADEGTK_MENU_LABEL, MENU_EDITOR_SEPARATOR_LABEL, - GLADEGTK_MENU_TOOLTIP, NULL, - -1); - if (submenu) - { - list.data = glade_widget_get_from_gobject (submenu); - glade_command_delete (&list); - } - - } - else - { - /* FIXME: Scrap this, write generic code that will - * loop over common GladeProperties and set them accordingly - * (other widget properties can be set through the normal - * editor/project-view selection, no need to loose these values). - */ - - glade_widget_copy_properties (gitem_new, gitem); - - if (submenu) - { - list.data = glade_widget_get_from_gobject (submenu); - glade_command_cut (&list); - glade_command_paste (&list, gitem_new, NULL); - } - } - - /* Delete old widget */ - list.data = gitem; - glade_command_delete (&list); - - gtk_widget_show_all (GTK_WIDGET (item_new)); - - gtk_tree_store_set (e->store, iter, - GLADEGTK_MENU_GWIDGET, gitem_new, - GLADEGTK_MENU_OBJECT, item_new, - GLADEGTK_MENU_TYPE_NAME, klass_name, - -1); - - glade_gtk_menu_editor_reorder_children (GTK_WIDGET (glade_widget_get_object (parent)), - GTK_TREE_MODEL (e->store), iter); - glade_gtk_menu_editor_select_child (e, gitem_new); - - g_free (name); - g_free (label); - g_free (tooltip); - - /* End of glade-command */ - glade_command_pop_group (); - - glade_gtk_menu_editor_block_callbacks (e, FALSE); -} - -static void -glade_gtk_menu_editor_item_type_edited (GtkCellRendererText *cell, - const gchar *path_string, - const gchar *new_text, - GladeGtkMenuEditor *e) -{ - GtkTreeModel *item_class; - GtkTreePath *path; - GtkTreeIter iter, combo_iter; - GladeWidgetClass *klass; - gchar *type_name; - - path = gtk_tree_path_new_from_string (path_string); - gtk_tree_model_get_iter (GTK_TREE_MODEL (e->store), &iter, path); - gtk_tree_model_get (GTK_TREE_MODEL (e->store), &iter, - GLADEGTK_MENU_TYPE_NAME, &type_name, - -1); - if (strcmp (type_name, new_text) == 0) - { - g_free (type_name); - return; - } - - /* Lookup GladeWidgetClass */ - item_class = glade_gtk_menu_editor_get_item_model (); - gtk_tree_model_get_iter_first (item_class, &combo_iter); - do - { - gtk_tree_model_get (item_class, &combo_iter, - GLADEGTK_MENU_ITEM_CLASS, &klass, - GLADEGTK_MENU_ITEM_NAME, &type_name, -1); - - if (strcmp (type_name, new_text) == 0) break; - - g_free (type_name); - } while (gtk_tree_model_iter_next (item_class, &combo_iter)); - - glade_gtk_menu_editor_item_change_type (e, &iter, klass, new_text); -} - -static gint -glade_gtk_menu_editor_popup_handler (GtkWidget *treeview, - GdkEventButton *event, - GladeGtkMenuEditor *e) -{ - GtkTreePath *path; - - if (event->button == 3) - { - if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview), - (gint) event->x, (gint) event->y, &path, NULL, NULL, NULL)) - { - gtk_tree_view_set_cursor (GTK_TREE_VIEW (treeview), path, NULL, FALSE); - gtk_tree_path_free (path); - } - - gtk_menu_popup (GTK_MENU (e->popup), NULL, NULL, NULL, NULL, - event->button, event->time); - return TRUE; - } - - return FALSE; -} - -static void -glade_gtk_menu_editor_reorder (GladeGtkMenuEditor *e, GtkTreeIter *iter) -{ - GladeWidget *gitem, *gparent; - GtkTreeIter parent_iter; - GObject *parent; - GList list = {0, }; - gchar *desc; - - desc = g_strdup_printf (_("Reorder %s's children"), - glade_widget_get_name (e->gmenubar)); - glade_command_push_group (desc); - g_free (desc); - - gtk_tree_model_get (GTK_TREE_MODEL (e->store), iter, GLADEGTK_MENU_GWIDGET, &gitem, -1); - - if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (e->store), &parent_iter, iter)) - { - GtkWidget *submenu; - gtk_tree_model_get (GTK_TREE_MODEL (e->store), &parent_iter, - GLADEGTK_MENU_OBJECT, &parent, - GLADEGTK_MENU_GWIDGET, &gparent, -1); - - if ((submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (parent)))) - gparent = glade_widget_get_from_gobject (submenu); - else - gparent = glade_command_create (glade_widget_class_get_by_type (GTK_TYPE_MENU), - gparent, NULL, e->project); - } - else - gparent = e->gmenubar; - - list.data = gitem; - glade_command_cut (&list); - glade_command_paste (&list, gparent, NULL); - - glade_gtk_menu_editor_reorder_children (GTK_WIDGET (glade_widget_get_object (gparent)), - GTK_TREE_MODEL (e->store), iter); - - glade_command_pop_group (); -} - -static gboolean -glade_gtk_menu_editor_drag_and_drop_idle (gpointer data) -{ - GladeGtkMenuEditor *e = (GladeGtkMenuEditor *) data; - - glade_gtk_menu_editor_reorder (e, &e->iter); - glade_gtk_menu_editor_clear (e); - gtk_tree_view_expand_all (GTK_TREE_VIEW (e->treeview)); - glade_gtk_menu_editor_set_cursor (e, &e->iter); - glade_gtk_menu_editor_block_callbacks (e, FALSE); - - return FALSE; -} - -static void -glade_gtk_menu_editor_row_inserted (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - GladeGtkMenuEditor *e) -{ - e->iter = *iter; - glade_gtk_menu_editor_block_callbacks (e, TRUE); - g_idle_add (glade_gtk_menu_editor_drag_and_drop_idle, e); -} - -static void -glade_gtk_menu_editor_add_item (GladeGtkMenuEditor *e, - GType type, - gboolean as_child) -{ - GtkTreeIter iter, new_iter; - GladeWidget *gparent, *gitem_new; - GValue val = {0, }; - const gchar *name; - gchar *desc; - - glade_gtk_menu_editor_block_callbacks (e, TRUE); - - desc = g_strdup_printf (_("Create a %s item"), glade_gtk_menu_editor_type_name (type)); - glade_command_push_group (desc); - g_free (desc); - - gparent = e->gmenubar; - - if (glade_gtk_menu_editor_get_item_selected (e, &iter)) - { - GObject *parent; - gtk_tree_model_get (GTK_TREE_MODEL (e->store), &iter, - GLADEGTK_MENU_OBJECT, &parent, - GLADEGTK_MENU_GWIDGET, &gparent, -1); - if (as_child) - { - GtkWidget *submenu; - if ((submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (parent)))) - gparent = glade_widget_get_from_gobject (submenu); - else - gparent = glade_command_create (glade_widget_class_get_by_type (GTK_TYPE_MENU), - gparent, NULL, glade_widget_get_project (gparent)); - - gtk_tree_store_append (GTK_TREE_STORE (e->store), &new_iter, &iter); - } - else - { - gtk_tree_store_insert_after (GTK_TREE_STORE (e->store), - &new_iter, NULL, &iter); - gparent = glade_widget_get_parent (gparent); - } - - } - else - gtk_tree_store_append (GTK_TREE_STORE (e->store), &new_iter, NULL); - - if (GTK_IS_SEPARATOR_MENU_ITEM (glade_widget_get_object (gparent))) - { - glade_command_pop_group (); - return; - } - - gitem_new = glade_command_create (glade_widget_class_get_by_type (type), - gparent, NULL, e->project); - - if (type == GTK_TYPE_SEPARATOR_MENU_ITEM) - { - name = MENU_EDITOR_SEPARATOR_LABEL; - } - else - { - name = glade_widget_get_name (gitem_new); - g_value_init (&val, G_TYPE_STRING); - g_value_set_string (&val, name); - glade_command_set_property (glade_widget_get_property (gitem_new, "label"), &val); - - g_value_unset(&val); - - g_value_init (&val, G_TYPE_BOOLEAN); - g_value_set_boolean (&val, TRUE); - glade_command_set_property (glade_widget_get_property (gitem_new, "use-underline"), &val); - } - - gtk_tree_store_set (GTK_TREE_STORE (e->store), &new_iter, - GLADEGTK_MENU_GWIDGET, gitem_new, - GLADEGTK_MENU_OBJECT, glade_widget_get_object (gitem_new), - GLADEGTK_MENU_TYPE_NAME, glade_gtk_menu_editor_type_name (type), - GLADEGTK_MENU_LABEL, name, - GLADEGTK_MENU_TOOLTIP, NULL, - -1); - - glade_gtk_menu_editor_reorder_children (GTK_WIDGET (glade_widget_get_object (gparent)), - GTK_TREE_MODEL (e->store), - &new_iter); - - gtk_tree_view_expand_all (GTK_TREE_VIEW (e->treeview)); - glade_gtk_menu_editor_set_cursor (e, &new_iter); - - glade_command_pop_group (); - - glade_gtk_menu_editor_block_callbacks (e, FALSE); -} - -static void -glade_gtk_menu_editor_add_item_activate (GtkMenuItem *menuitem, - GladeGtkMenuEditor *e) -{ - glade_gtk_menu_editor_add_item (e, GTK_TYPE_MENU_ITEM, FALSE); -} - -static void -glade_gtk_menu_editor_add_child_item_activate (GtkMenuItem *menuitem, - GladeGtkMenuEditor *e) -{ - glade_gtk_menu_editor_add_item (e, GTK_TYPE_MENU_ITEM, TRUE); -} - -static void -glade_gtk_menu_editor_add_separator_activate (GtkMenuItem *menuitem, - GladeGtkMenuEditor *e) -{ - glade_gtk_menu_editor_add_item (e, GTK_TYPE_SEPARATOR_MENU_ITEM, FALSE); -} - -static void -glade_gtk_menu_editor_delete_item (GladeGtkMenuEditor *e) -{ - GtkTreeIter iter; - GList list = {0, }; - - if (glade_gtk_menu_editor_get_item_selected (e, &iter)) - { - gtk_tree_model_get (GTK_TREE_MODEL (e->store), &iter, - GLADEGTK_MENU_GWIDGET, &list.data, -1); - - gtk_tree_store_remove (e->store, &iter); - glade_command_delete (&list); - - glade_gtk_menu_editor_clear (e); - } -} - -#include <gdk/gdkkeysyms.h> -gboolean -glade_gtk_menu_editor_treeview_key_press_event (GtkWidget *widget, - GdkEventKey *event, - GladeGtkMenuEditor *e) -{ - if (event->keyval == GDK_Delete) - glade_gtk_menu_editor_delete_item (e); - - return FALSE; -} - -static void -glade_gtk_menu_editor_delete_item_activate (GtkMenuItem *menuitem, - GladeGtkMenuEditor *e) -{ - glade_gtk_menu_editor_delete_item (e); -} - -static void -glade_gtk_menu_editor_help (GtkButton *button, GtkWidget *window) -{ - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (GTK_WINDOW (window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, " "); - - gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), - _("<big><b>Tips:</b></big>\n" - " * Right click over the treeview to add items.\n" - " * Press Delete to remove the selected item.\n" - " * Drag & Drop to reorder.\n" - " * Type column is editable.")); - - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); -} - -static gboolean -glade_gtk_menu_editor_is_child (GladeGtkMenuEditor *e, GladeWidget *item) -{ - if (!GTK_IS_MENU_ITEM (glade_widget_get_object (item))) - return FALSE; - - while ((item = glade_widget_get_parent (item))) - if (item == e->gmenubar) return TRUE; - - return FALSE; -} - -static gboolean -glade_gtk_menu_editor_update_treeview_idle (gpointer data) -{ - GladeGtkMenuEditor *e = (GladeGtkMenuEditor *) data; - GList *selection = glade_project_selection_get (e->project); - GladeWidget *widget; - - glade_gtk_menu_editor_block_callbacks (e, TRUE); - - gtk_tree_store_clear (e->store); - glade_gtk_menu_editor_fill_store (GTK_WIDGET (glade_widget_get_object (e->gmenubar)), - e->store, NULL); - glade_gtk_menu_editor_clear (e); - - gtk_tree_view_expand_all (GTK_TREE_VIEW (e->treeview)); - - if (selection) - { - widget = glade_widget_get_from_gobject (G_OBJECT (selection->data)); - if (glade_gtk_menu_editor_is_child (e, widget)) - glade_gtk_menu_editor_select_child (e, widget); - } - - glade_gtk_menu_editor_block_callbacks (e, FALSE); - - return FALSE; -} - -static void -glade_gtk_menu_editor_project_remove_widget (GladeProject *project, - GladeWidget *widget, - GladeGtkMenuEditor *e) -{ - if (widget == e->gmenubar) - { - gtk_widget_destroy (e->window); - return; - } - - if (glade_gtk_menu_editor_is_child (e, widget)) - { - GtkTreeIter iter; - if (glade_gtk_menu_editor_find_child (e, widget, &iter)) - { - gtk_tree_store_remove (e->store, &iter); - glade_gtk_menu_editor_clear (e); - } - } -} - -static void -glade_gtk_menu_editor_project_add_widget (GladeProject *project, - GladeWidget *widget, - GladeGtkMenuEditor *e) -{ - if (glade_gtk_menu_editor_is_child (e, widget)) - g_idle_add (glade_gtk_menu_editor_update_treeview_idle, e); -} - -static void -glade_gtk_menu_editor_block_callbacks (GladeGtkMenuEditor *e, gboolean block) -{ - if (block) - { - g_signal_handlers_block_by_func (e->store, glade_gtk_menu_editor_row_inserted, e); - g_signal_handlers_block_by_func (e->project, glade_gtk_menu_editor_project_remove_widget, e); - g_signal_handlers_block_by_func (e->project, glade_gtk_menu_editor_project_add_widget, e); - } - else - { - g_signal_handlers_unblock_by_func (e->store, glade_gtk_menu_editor_row_inserted, e); - g_signal_handlers_unblock_by_func (e->project, glade_gtk_menu_editor_project_remove_widget, e); - g_signal_handlers_unblock_by_func (e->project, glade_gtk_menu_editor_project_add_widget, e); - } -} - -static void -glade_gtk_menu_editor_project_widget_name_changed (GladeProject *project, - GladeWidget *widget, - GladeGtkMenuEditor *e) -{ - /* Deffer this to an idle handler, calling _select_child() here - * directly causes crashes deep in the _set_cursor() code. - */ - g_idle_add (glade_gtk_menu_editor_update_treeview_idle, e); -} - -static void -glade_gtk_menu_editor_project_closed (GladeProject *project, - GladeGtkMenuEditor *e) -{ - e->project = NULL; - gtk_widget_destroy (e->window); -} - -static gboolean -glade_gtk_menu_editor_destroyed (GtkWidget *window, GladeGtkMenuEditor *e) -{ - if (e->project) - { - g_signal_handlers_disconnect_by_func (e->project, - glade_gtk_menu_editor_project_closed, e); - - g_signal_handlers_disconnect_by_func (e->project, - glade_gtk_menu_editor_project_remove_widget, e); - - g_signal_handlers_disconnect_by_func (e->project, - glade_gtk_menu_editor_project_add_widget, e); - - g_signal_handlers_disconnect_by_func (e->project, - glade_gtk_menu_editor_project_widget_name_changed, e); - } - - g_object_set_data (glade_widget_get_object (e->gmenubar), - "GladeGtkMenuEditor", NULL); - - g_free (e); - - return FALSE; -} - -static -GladeGtkMenuEditor * -glade_gtk_menu_editor_new (GObject *menubar) +void GLADEGTK_API +glade_gtk_menu_bar_launch_editor (GObject *menubar) { - GladeGtkMenuEditor *e; - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - GtkWidget *vbox, *signal_editor_w, *paned, *hbox, *prop_vbox, *tree_vbox; - GtkWidget *label, *scroll, *item, *button, *buttonbox, *button_table; - gchar *title; - - if (menubar == NULL) return NULL; - - if (g_object_get_data (menubar, "GladeGtkMenuEditor")) return NULL; - - /* Editor's struct */ - e = g_malloc0 (sizeof (GladeGtkMenuEditor)); - g_object_set_data (menubar, "GladeGtkMenuEditor", e); - - e->gmenubar = glade_widget_get_from_gobject (menubar); - - e->project = glade_widget_get_project (e->gmenubar); - - g_signal_connect (e->project, "close", - G_CALLBACK (glade_gtk_menu_editor_project_closed), - e); - - g_signal_connect (e->project, "remove-widget", - G_CALLBACK (glade_gtk_menu_editor_project_remove_widget), - e); - - g_signal_connect (e->project, "add-widget", - G_CALLBACK (glade_gtk_menu_editor_project_add_widget), - e); - - g_signal_connect (e->project, "widget-name-changed", - G_CALLBACK (glade_gtk_menu_editor_project_widget_name_changed), - e); - - /* Store */ - e->store = gtk_tree_store_new (GLADEGTK_MENU_N_COLUMNS, - G_TYPE_OBJECT, - G_TYPE_OBJECT, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_BOOLEAN); - glade_gtk_menu_editor_fill_store (GTK_WIDGET (menubar), e->store, NULL); - g_signal_connect (e->store, "row-inserted", G_CALLBACK (glade_gtk_menu_editor_row_inserted), e); - - /* Window */ - e->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_modal (GTK_WINDOW (e->window), TRUE); - gtk_window_set_type_hint (GTK_WINDOW (e->window), GDK_WINDOW_TYPE_HINT_DIALOG); - g_signal_connect (e->window, "destroy", G_CALLBACK (glade_gtk_menu_editor_destroyed), e); - - title = g_strdup_printf ("%s - %s", _("Menu Bar Editor"), glade_widget_get_name (e->gmenubar)); - gtk_window_set_title (GTK_WINDOW (e->window), title); - g_free (title); - - /* Vbox */ - vbox = gtk_vbox_new (FALSE, 8); - gtk_widget_show (vbox); - gtk_container_set_border_width (GTK_CONTAINER (vbox), GLADE_GENERIC_BORDER_WIDTH); - gtk_container_add (GTK_CONTAINER (e->window), vbox); - - /* Paned */ - paned = gtk_vpaned_new (); - gtk_widget_show (paned); - gtk_box_pack_start (GTK_BOX (vbox), paned, TRUE, TRUE, 0); - - /* Hbox */ - hbox = gtk_hbox_new (FALSE, 8); - gtk_widget_show (hbox); - gtk_paned_pack1 (GTK_PANED (paned), hbox, TRUE, FALSE); - - /* TreeView Vbox */ - tree_vbox = gtk_vbox_new (FALSE, 8); - gtk_widget_show (tree_vbox); - gtk_box_pack_start (GTK_BOX (hbox), tree_vbox, FALSE, TRUE, 0); - - /* ScrolledWindow */ - scroll = gtk_scrolled_window_new (NULL, NULL); - gtk_widget_show (scroll); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - gtk_box_pack_start (GTK_BOX (tree_vbox), scroll, TRUE, TRUE, 0); - - /* TreeView */ - e->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (e->store)); - gtk_widget_show (e->treeview); - gtk_tree_view_expand_all (GTK_TREE_VIEW (e->treeview)); - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (e->treeview), TRUE); - gtk_tree_view_set_reorderable (GTK_TREE_VIEW (e->treeview), TRUE); - - gtk_widget_add_events (e->treeview, GDK_KEY_PRESS_MASK); - g_signal_connect (e->treeview, "key-press-event", - G_CALLBACK (glade_gtk_menu_editor_treeview_key_press_event), e); - - g_signal_connect (e->treeview, "cursor_changed", - G_CALLBACK (glade_gtk_menu_editor_treeview_cursor_changed), e); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Label"), renderer, - "text", GLADEGTK_MENU_LABEL, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (e->treeview), column); - - renderer = gtk_cell_renderer_combo_new (); - g_object_set (renderer, - "model", glade_gtk_menu_editor_get_item_model(), - "text-column", GLADEGTK_MENU_ITEM_NAME, - "has-entry", FALSE, - "editable", TRUE, - NULL); - g_signal_connect (renderer, "edited", - G_CALLBACK (glade_gtk_menu_editor_item_type_edited), e); - column = gtk_tree_view_column_new_with_attributes (_("Type"), renderer, - "text", GLADEGTK_MENU_TYPE_NAME, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (e->treeview), column); - - gtk_container_add (GTK_CONTAINER (scroll), e->treeview); - - /* Add/Remove buttons */ - button_table = gtk_table_new (1, 2, TRUE); - gtk_widget_show (button_table); - gtk_table_set_col_spacings (GTK_TABLE (button_table), 8); - gtk_box_pack_start (GTK_BOX (tree_vbox), button_table, FALSE, TRUE, 0); - - button = gtk_button_new_from_stock (GTK_STOCK_ADD); - gtk_widget_show (button); - g_signal_connect (button, "clicked", - G_CALLBACK (glade_gtk_menu_editor_add_item_activate), e); - gtk_table_attach_defaults (GTK_TABLE (button_table), button, 0, 1, 0, 1); - - e->remove_button = button = gtk_button_new_from_stock (GTK_STOCK_REMOVE); - gtk_widget_show (button); - g_signal_connect (button, "clicked", - G_CALLBACK (glade_gtk_menu_editor_delete_item_activate), e); - gtk_table_attach_defaults (GTK_TABLE (button_table), button, 1, 2, 0, 1); - - /* PopUp */ - e->popup = gtk_menu_new (); - - item = gtk_menu_item_new_with_label (_("Add Item")); - g_signal_connect (item, "activate", - G_CALLBACK (glade_gtk_menu_editor_add_item_activate), e); - gtk_menu_shell_append (GTK_MENU_SHELL (e->popup), item); - - item = gtk_menu_item_new_with_label (_("Add Child Item")); - g_signal_connect (item, "activate", G_CALLBACK (glade_gtk_menu_editor_add_child_item_activate), e); - gtk_menu_shell_append (GTK_MENU_SHELL (e->popup), item); - - item = gtk_menu_item_new_with_label (_("Add Separator")); - g_signal_connect (item, "activate", G_CALLBACK (glade_gtk_menu_editor_add_separator_activate), e); - gtk_menu_shell_append (GTK_MENU_SHELL (e->popup), item); - - gtk_widget_show_all (e->popup); - g_signal_connect (e->treeview, "button_press_event", G_CALLBACK (glade_gtk_menu_editor_popup_handler), e); - - /* Properties Vbox */ - prop_vbox = gtk_vbox_new (FALSE, 8); - gtk_widget_show (prop_vbox); - gtk_box_pack_start (GTK_BOX (hbox), prop_vbox, TRUE, TRUE, 0); - - /* Properties label */ - label = gtk_label_new (NULL); - gtk_widget_show (label); - gtk_label_set_markup (GTK_LABEL (label), _("<span rise=\"-20000\"><b>Menu Item</b></span>")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); - gtk_box_pack_start (GTK_BOX (prop_vbox), label, FALSE, TRUE, 0); - - /* Tables */ - e->table = gtk_table_new (1, 2, FALSE); - gtk_widget_show (e->table); - gtk_table_set_row_spacings (GTK_TABLE (e->table), 4); - gtk_box_pack_start (GTK_BOX (prop_vbox), e->table, FALSE, TRUE, 0); - - e->child_table = gtk_table_new (1, 2, FALSE); - gtk_widget_show (e->child_table); - gtk_table_set_row_spacings (GTK_TABLE (e->child_table), 4); - gtk_box_pack_start (GTK_BOX (prop_vbox), e->child_table, FALSE, TRUE, 0); - - /* Signal Editor */ - e->signal_editor = glade_signal_editor_new (NULL); - signal_editor_w = glade_signal_editor_get_widget (e->signal_editor); - gtk_widget_show (signal_editor_w); - gtk_widget_set_size_request (signal_editor_w, -1, 96); - gtk_paned_pack2 (GTK_PANED (paned), signal_editor_w, FALSE, FALSE); - - /* Button Box */ - buttonbox = gtk_hbutton_box_new (); - gtk_widget_show (buttonbox); - gtk_button_box_set_layout (GTK_BUTTON_BOX (buttonbox), GTK_BUTTONBOX_END); - gtk_box_set_spacing (GTK_BOX (buttonbox), 8); - gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, TRUE, 0); - - button = glade_app_undo_button_new (); - gtk_widget_show (button); - gtk_container_add (GTK_CONTAINER (buttonbox), button); - - button = glade_app_redo_button_new (); - gtk_widget_show (button); - gtk_container_add (GTK_CONTAINER (buttonbox), button); - - button = gtk_button_new_from_stock (GTK_STOCK_CLOSE); - gtk_widget_show (button); - g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), e->window); - gtk_container_add (GTK_CONTAINER (buttonbox), button); - - button = gtk_button_new_from_stock (GTK_STOCK_HELP); - gtk_widget_show (button); - g_signal_connect (button, "clicked", G_CALLBACK (glade_gtk_menu_editor_help), e->window); - gtk_container_add (GTK_CONTAINER (buttonbox), button); - gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (buttonbox), button, TRUE); - - return e; + glade_gtk_menu_shell_launch_editor (menubar, _("Menu Bar Editor")); } +/* ------------------------------ GtkMenu -------------------------------- */ void GLADEGTK_API -glade_gtk_menu_bar_launch_editor (GObject *menubar) +glade_gtk_menu_launch_editor (GObject *menu) { - GladeGtkMenuEditor *editor; - - if ((editor = glade_gtk_menu_editor_new (menubar))) - { - gtk_window_set_default_size (GTK_WINDOW (editor->window), 600, 440); - gtk_widget_show (editor->window); - return; - } - else - { - GladeWidget *gmenubar = glade_widget_get_from_gobject (menubar); - glade_util_ui_message (GTK_WIDGET (glade_app_get_transient_parent ()), - GLADE_UI_INFO, - _("A MenuBar editor is already runing for \"%s\"\n" - "Cannot launch more than one editor per menubar."), - (gmenubar) ? glade_widget_get_name (gmenubar) : _("unknown")); - } + glade_gtk_menu_shell_launch_editor (menu, _("Menu Editor")); } - /* ----------------------------- GtkToolBar ------------------------------ */ void GLADEGTK_API glade_gtk_toolbar_get_child_property (GObject *container, @@ -5152,6 +4038,96 @@ glade_gtk_toolbar_remove_child (GObject *object, GObject *child) gtk_container_remove (GTK_CONTAINER (object), GTK_WIDGET (child)); } +static gchar * +glade_gtk_toolbar_get_display_name (GladeBaseEditor *editor, + GladeWidget *gchild, + gpointer user_data) +{ + GObject *child = glade_widget_get_object (gchild); + gchar *name; + + if (GTK_IS_SEPARATOR_TOOL_ITEM (child)) + name = _("<separator>"); + else + if (GTK_IS_TOOL_BUTTON (child)) + { + glade_widget_property_get (gchild, "label", &name); + if (name == NULL || strlen (name) == 0) + glade_widget_property_get (gchild, "stock-id", &name); + } + else + name = _("<custom>"); + + return g_strdup (name); +} + +static void +glade_gtk_toolbar_child_selected (GladeBaseEditor *editor, + GladeWidget *gchild, + gpointer data) +{ + GObject *child = glade_widget_get_object (gchild); + GType type = G_OBJECT_TYPE (child); + + glade_base_editor_add_label (editor, "Tool Item"); + + glade_base_editor_add_default_properties (editor, gchild); + + glade_base_editor_add_label (editor, "Properties"); + + glade_base_editor_add_properties (editor, gchild, + "visible-horizontal", + "visible-vertical", + NULL); + + if (type == GTK_TYPE_SEPARATOR_TOOL_ITEM) return; + + if (GTK_IS_TOOL_BUTTON (child)) + glade_base_editor_add_properties (editor, gchild, + "label", + "glade-type", + "icon", + "glade-stock", + "icon-name", + NULL); + + if (type == GTK_TYPE_RADIO_TOOL_BUTTON) + glade_base_editor_add_properties (editor, gchild, + "group", "active", NULL); +} + +void GLADEGTK_API +glade_gtk_toolbar_launch_editor (GObject *toolbar) +{ + GladeBaseEditor *editor; + GtkWidget *window; + /* Editor */ + editor = glade_base_editor_new (toolbar, FALSE, + _("Button"), GTK_TYPE_TOOL_BUTTON, + _("Toggle"), GTK_TYPE_TOGGLE_TOOL_BUTTON, + _("Radio"), GTK_TYPE_RADIO_TOOL_BUTTON, + _("Menu"), GTK_TYPE_MENU_TOOL_BUTTON, + _("Item"), GTK_TYPE_TOOL_ITEM, + _("Separator"), GTK_TYPE_SEPARATOR_TOOL_ITEM, + NULL); + + glade_base_editor_add_popup_items (editor, + _("Add Tool Button"), GTK_TYPE_TOOL_BUTTON, FALSE, + _("Add Toggle Button"), GTK_TYPE_TOGGLE_TOOL_BUTTON, FALSE, + _("Add Radio Button"), GTK_TYPE_RADIO_TOOL_BUTTON, FALSE, + _("Add Menu Button"), GTK_TYPE_MENU_TOOL_BUTTON, FALSE, + _("Add Tool Item"), GTK_TYPE_TOOL_ITEM, FALSE, + _("Add Separator"), GTK_TYPE_SEPARATOR_TOOL_ITEM, FALSE, + NULL); + + g_signal_connect (editor, "get-display-name", G_CALLBACK (glade_gtk_toolbar_get_display_name), NULL); + g_signal_connect (editor, "child-selected", G_CALLBACK (glade_gtk_toolbar_child_selected), NULL); + + gtk_widget_show (GTK_WIDGET (editor)); + + window = glade_base_editor_pack_new_window (editor, _("Tool Bar Editor"), NULL); + gtk_widget_show (window); +} /* ----------------------------- GtkToolItem ------------------------------ */ void GLADEGTK_API diff --git a/src/glade-marshallers.list b/src/glade-marshallers.list index db5386c9..99431ed8 100644 --- a/src/glade-marshallers.list +++ b/src/glade-marshallers.list @@ -4,7 +4,11 @@ VOID:OBJECT VOID:OBJECT,BOOLEAN VOID:STRING,STRING,STRING OBJECT:POINTER +OBJECT:OBJECT,UINT BOOLEAN:OBJECT BOOLEAN:BOXED BOOLEAN:OBJECT,POINTER BOOLEAN:OBJECT,BOOLEAN +BOOLEAN:OBJECT,UINT +BOOLEAN:OBJECT,OBJECT +STRING:OBJECT diff --git a/src/glade-project.c b/src/glade-project.c index 2fb7839b..937586f6 100644 --- a/src/glade-project.c +++ b/src/glade-project.c @@ -1336,7 +1336,7 @@ glade_project_write (GladeProject *project) * Append toplevel widgets. Each widget then takes * care of appending its children. */ - if (g_type_is_a (widget->widget_class->type, GTK_TYPE_WINDOW)) + if (widget->parent == NULL && widget->widget_class->toplevel) { info = glade_widget_write (widget, interface); if (!info) diff --git a/src/glade-property.c b/src/glade-property.c index f18fa617..d2e6e713 100644 --- a/src/glade-property.c +++ b/src/glade-property.c @@ -214,6 +214,7 @@ glade_property_set_value_impl (GladeProperty *property, const GValue *value) GladeProject *project = property->widget ? glade_widget_get_project (property->widget) : NULL; gboolean changed = FALSE; + GValue old_value = {0,}; if (!g_value_type_compatible (G_VALUE_TYPE (property->value), G_VALUE_TYPE (value))) { @@ -245,6 +246,10 @@ glade_property_set_value_impl (GladeProperty *property, const GValue *value) glade_property_update_prop_refs (property, property->value, value); + /* Make a copy of the old value */ + g_value_init (&old_value, G_VALUE_TYPE (property->value)); + g_value_copy (property->value, &old_value); + /* Assign property first so that; if the object need be * rebuilt, it will reflect the new value */ @@ -257,8 +262,10 @@ glade_property_set_value_impl (GladeProperty *property, const GValue *value) { g_signal_emit (G_OBJECT (property), glade_property_signals[VALUE_CHANGED], - 0, property->value); + 0, &old_value, property->value); } + + g_value_unset (&old_value); } static void @@ -649,8 +656,8 @@ glade_property_klass_init (GladePropertyKlass *prop_class) G_STRUCT_OFFSET (GladePropertyKlass, value_changed), NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); + glade_marshal_VOID__POINTER_POINTER, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); glade_property_signals[TOOLTIP_CHANGED] = g_signal_new ("tooltip-changed", diff --git a/src/glade-property.h b/src/glade-property.h index 3ed8be7f..7916f744 100644 --- a/src/glade-property.h +++ b/src/glade-property.h @@ -75,7 +75,7 @@ struct _GladePropertyKlass G_CONST_RETURN gchar * (* get_tooltip) (GladeProperty *); /* Signals */ - void (* value_changed) (GladeProperty *, GValue *); + void (* value_changed) (GladeProperty *, GValue *, GValue *); void (* tooltip_changed) (GladeProperty *, const gchar *); }; diff --git a/src/glade-widget-class.c b/src/glade-widget-class.c index 94b088f4..f288b681 100644 --- a/src/glade-widget-class.c +++ b/src/glade-widget-class.c @@ -683,6 +683,10 @@ glade_widget_class_extend_with_node (GladeWidgetClass *widget_class, widget_class->fixed = glade_xml_get_property_boolean (node, GLADE_TAG_FIXED, widget_class->fixed); + /* Check if this class is toplevel */ + widget_class->toplevel = glade_xml_get_property_boolean (node, + GLADE_XML_TAG_TOPLEVEL, + FALSE); /* if we found a <properties> tag on the xml file, we add the properties * that we read from the xml file to the class. @@ -1000,6 +1004,9 @@ glade_widget_class_merge (GladeWidgetClass *widget_class, if (widget_class->launch_editor == NULL) widget_class->launch_editor = parent_class->launch_editor; + if (widget_class->toplevel == FALSE) + widget_class->toplevel = parent_class->toplevel; + /* merge the parent's properties */ glade_widget_class_merge_properties (parent_class->type, @@ -1100,6 +1107,7 @@ glade_widget_class_new (GladeXmlNode *class_node, widget_class->cursor = NULL; widget_class->large_icon = NULL; widget_class->small_icon = NULL; + widget_class->toplevel = FALSE; if (G_TYPE_IS_INSTANTIATABLE (widget_class->type) && G_TYPE_IS_ABSTRACT (widget_class->type) == FALSE && diff --git a/src/glade-widget-class.h b/src/glade-widget-class.h index cba1446e..26fb864d 100644 --- a/src/glade-widget-class.h +++ b/src/glade-widget-class.h @@ -208,7 +208,9 @@ struct _GladeWidgetClass * and the set & get functions of the properties * of this class. */ - + + gboolean toplevel; /* If this class is toplevel */ + /* Executed after widget creation: it takes care of creating the * GladeWidgets associated with internal children. It's also the place * to set sane defaults, e.g. set the size of a window. diff --git a/src/glade.h b/src/glade.h index 7b5945d8..b9c65a4d 100644 --- a/src/glade.h +++ b/src/glade.h @@ -70,6 +70,7 @@ typedef enum _GladeItemAppearance GladeItemAppearance; #define GLADE_XML_TAG_PACKING "packing" #define GLADE_XML_TAG_PLACEHOLDER "placeholder" #define GLADE_XML_TAG_INTERNAL_CHILD "internal-child" +#define GLADE_XML_TAG_TOPLEVEL "toplevel" /* Used for catalog tags and attributes */ #define GLADE_TAG_GLADE_CATALOG "glade-catalog" diff --git a/widgets/gtk+.xml.in b/widgets/gtk+.xml.in index 8c3d8655..39a76ee9 100644 --- a/widgets/gtk+.xml.in +++ b/widgets/gtk+.xml.in @@ -125,7 +125,7 @@ </children> </glade-widget-class> - <glade-widget-class name="GtkWindow" generic-name="window" _title="Window"> + <glade-widget-class name="GtkWindow" generic-name="window" _title="Window" toplevel="True"> <post-create-function>glade_gtk_window_post_create</post-create-function> <properties> @@ -309,6 +309,7 @@ <glade-widget-class name="GtkToolbar" generic-name="toolbar" _title="Tool Bar"> <post-create-function>empty</post-create-function> + <launch-editor-function>glade_gtk_toolbar_launch_editor</launch-editor-function> <properties> <property id="orientation"> <displayable-values> @@ -352,7 +353,7 @@ <post-create-function>glade_gtk_tool_item_post_create</post-create-function> </glade-widget-class> - <glade-widget-class name="GtkSeparatorToolItem" generic-name="separatortoolbutton" _title="Separator Tool Item"/> + <glade-widget-class name="GtkSeparatorToolItem" generic-name="separatortoolitem" _title="Separator Tool Item"/> <glade-widget-class name="GtkToolButton" generic-name="toolbutton" _title="Tool Button"> <properties> @@ -459,6 +460,7 @@ </glade-widget-class> <glade-widget-class name="GtkTextView" generic-name="textview" _title="Text View"> + <post-create-function>empty</post-create-function> <properties> <property id="justification"> <displayable-values> @@ -923,9 +925,10 @@ <glade-widget-class name="GtkCalendar" generic-name="calendar" _title="Calendar"/> - <glade-widget-class name="GtkMenu" generic-name="menu" _title="Popup Menu"> + <glade-widget-class name="GtkMenu" generic-name="menu" _title="Popup Menu" toplevel="True"> <!-- We do not want glade_gtk_container_post_create be executed --> <post-create-function>empty</post-create-function> + <launch-editor-function>glade_gtk_menu_launch_editor</launch-editor-function> </glade-widget-class> <glade-widget-class name="GtkHScrollbar" generic-name="hscrollbar" _title="Horizontal Scrollbar"/> |