summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Pablo Ugarte <jpu@src.gnome.org>2006-07-13 21:38:19 +0000
committerJuan Pablo Ugarte <jpu@src.gnome.org>2006-07-13 21:38:19 +0000
commit0c4e3578b1c9f6a38e14968d1fc6f3bef23daa14 (patch)
treef8093d642c0a3981e326080ad8f63a3c5e79fffb
parent8ce781c124bd8364fbf0640324cc4254dadf4cb9 (diff)
downloadglade-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--ChangeLog36
-rw-r--r--TODO2
-rw-r--r--doc/widgetclasses.sgml10
-rw-r--r--po/POTFILES.in2
-rw-r--r--src/Makefile.am4
-rw-r--r--src/glade-accumulators.c27
-rw-r--r--src/glade-accumulators.h18
-rw-r--r--src/glade-app.c2
-rw-r--r--src/glade-base-editor.c1876
-rw-r--r--src/glade-base-editor.h100
-rw-r--r--src/glade-command.c2
-rw-r--r--src/glade-editor-property.c1
-rw-r--r--src/glade-gtk.c1726
-rw-r--r--src/glade-marshallers.list4
-rw-r--r--src/glade-project.c2
-rw-r--r--src/glade-property.c13
-rw-r--r--src/glade-property.h2
-rw-r--r--src/glade-widget-class.c8
-rw-r--r--src/glade-widget-class.h4
-rw-r--r--src/glade.h1
-rw-r--r--widgets/gtk+.xml.in9
21 files changed, 2454 insertions, 1395 deletions
diff --git a/ChangeLog b/ChangeLog
index 0ac1c718..7336eea9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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:
diff --git a/TODO b/TODO
index 7c323150..64ec573a 100644
--- a/TODO
+++ b/TODO
@@ -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 &amp; 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 &amp; 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"/>