glade3 r2094 - in trunk: . gladeui plugins/gnome src



Author: jpu
Date: Tue Jan 20 22:25:11 2009
New Revision: 2094
URL: http://svn.gnome.org/viewvc/glade3?rev=2094&view=rev

Log:
* gladeui/glade-design-layout.[ch]: added GladeDesignLayout::widget-event
  signal. Patch by Pavel Kostyuchenko (bug 542337).

* gladeui/glade-accumulators.[ch]: added glade_integer_handled_accumulator()

* gladeui/glade-signal-editor.[ch], gladeui/glade-signal-editor.[ch],
  gladeui/glade-app.[ch], src/glade-window.c: 
  "Improvement of GladeSignalEditor" Bug 540691 by Pavel Kostyuchenko.

* plugins/gnome/glade-gnome.c: Fixed compiler warnings in
  glade_gnome_bonobodockitem_get_props()


Modified:
   trunk/ChangeLog
   trunk/gladeui/glade-accumulators.c
   trunk/gladeui/glade-accumulators.h
   trunk/gladeui/glade-app.c
   trunk/gladeui/glade-app.h
   trunk/gladeui/glade-design-layout.c
   trunk/gladeui/glade-design-layout.h
   trunk/gladeui/glade-editor.c
   trunk/gladeui/glade-editor.h
   trunk/gladeui/glade-marshallers.list
   trunk/gladeui/glade-signal-editor.c
   trunk/gladeui/glade-signal-editor.h
   trunk/plugins/gnome/glade-gnome.c
   trunk/src/glade-window.c

Modified: trunk/gladeui/glade-accumulators.c
==============================================================================
--- trunk/gladeui/glade-accumulators.c	(original)
+++ trunk/gladeui/glade-accumulators.c	Tue Jan 20 22:25:11 2009
@@ -42,6 +42,22 @@
 	return (object == NULL);
 }
 
+gboolean
+glade_integer_handled_accumulator (GSignalInvocationHint *ihint,
+				   GValue                *return_accu,
+				   const GValue          *handler_return,
+				   gpointer               dummy)
+{
+	gboolean continue_emission;
+	gint retval;
+	
+	retval = g_value_get_int (handler_return);
+	g_value_set_int (return_accu, retval >> 1);
+	continue_emission = !(retval & 1);
+	
+	return continue_emission;
+}
+
 /* From gtkmain.c */
 gboolean
 glade_boolean_handled_accumulator (GSignalInvocationHint *ihint,

Modified: trunk/gladeui/glade-accumulators.h
==============================================================================
--- trunk/gladeui/glade-accumulators.h	(original)
+++ trunk/gladeui/glade-accumulators.h	Tue Jan 20 22:25:11 2009
@@ -10,6 +10,11 @@
 					    GValue                *return_accu,
 					    const GValue          *handler_return,
 					    gpointer               dummy);
+
+gboolean glade_integer_handled_accumulator (GSignalInvocationHint *ihint,
+					    GValue                *return_accu,
+					    const GValue          *handler_return,
+					    gpointer               dummy);
 					    
 gboolean glade_boolean_handled_accumulator (GSignalInvocationHint *ihint,
 					    GValue                *return_accu,

Modified: trunk/gladeui/glade-app.c
==============================================================================
--- trunk/gladeui/glade-app.c	(original)
+++ trunk/gladeui/glade-app.c	Tue Jan 20 22:25:11 2009
@@ -56,6 +56,7 @@
 enum
 {
 	UPDATE_UI,
+	SIGNAL_EDITOR_CREATED,
 	LAST_SIGNAL
 };
 
@@ -288,6 +289,12 @@
 			glade_app_refresh_undo_redo_button (app, list->data, FALSE);
 }
 
+static void
+glade_app_signal_editor_created_default (GladeApp *app, GladeSignalEditor *signal_editor)
+{
+	glade_signal_editor_construct_signals_list (signal_editor);
+}
+
 static gboolean
 clipboard_view_on_delete_cb (GtkWidget *clipboard_view, GdkEvent *e, GladeApp *app)
 {
@@ -396,6 +403,8 @@
 	static gboolean initialized = FALSE;
 	
 	app->priv = GLADE_APP_GET_PRIVATE (app);	
+
+	singleton_app = app;
 	
 	glade_init_check ();	
 	
@@ -453,6 +462,7 @@
 	object_class->set_property = glade_app_set_property;
 
 	klass->update_ui_signal = glade_app_update_ui_default;
+	klass->signal_editor_created = glade_app_signal_editor_created_default;
 	klass->show_properties  = NULL;
 	klass->hide_properties  = NULL;
 
@@ -472,6 +482,26 @@
 			      g_cclosure_marshal_VOID__VOID,
 			      G_TYPE_NONE, 0);
 
+	/**
+	 * GladeApp::signal-editor-created:
+	 * @gladeapp: the #GladeApp which received the signal.
+	 * @signal_editor: the new #GladeSignalEditor.
+	 *
+	 * Emitted when a new signal editor created.
+	 * A tree view is created in the default handler.
+	 * Connect your handler before the default handler for setting a custom column or renderer
+	 * and after it for connecting to the tree view signals
+	 */
+	glade_app_signals[SIGNAL_EDITOR_CREATED] =
+		g_signal_new ("signal-editor-created",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GladeAppClass,
+					       signal_editor_created),
+			      NULL, NULL,
+			      glade_marshal_VOID__OBJECT,
+			      G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
 	g_object_class_install_property 
 		(object_class, PROP_ACTIVE_PROJECT,
 		 g_param_spec_object 

Modified: trunk/gladeui/glade-app.h
==============================================================================
--- trunk/gladeui/glade-app.h	(original)
+++ trunk/gladeui/glade-app.h	Tue Jan 20 22:25:11 2009
@@ -82,6 +82,7 @@
 
 	/* signals */
 	void   (* update_ui_signal) (GladeApp    *app);
+	void   (* signal_editor_created) (GladeApp *app, GladeSignalEditor *signal_editor);
 };
 
  

Modified: trunk/gladeui/glade-design-layout.c
==============================================================================
--- trunk/gladeui/glade-design-layout.c	(original)
+++ trunk/gladeui/glade-design-layout.c	Tue Jan 20 22:25:11 2009
@@ -27,6 +27,8 @@
 
 #include "glade.h"
 #include "glade-design-layout.h"
+#include "glade-accumulators.h"
+#include "glade-marshallers.h"
 
 #include <gtk/gtk.h>
 
@@ -56,6 +58,12 @@
 	REGION_OUTSIDE
 } PointerRegion;
 
+enum
+{
+	WIDGET_EVENT,
+	LAST_SIGNAL
+};
+
 struct _GladeDesignLayoutPrivate
 {
 	GdkWindow *event_window;
@@ -73,6 +81,8 @@
 	gint new_height;            /* user's new requested height */
 };
 
+static guint              glade_design_layout_signals[LAST_SIGNAL] = {0};
+
 G_DEFINE_TYPE (GladeDesignLayout, glade_design_layout, GTK_TYPE_BIN)
 
 static PointerRegion
@@ -839,7 +849,8 @@
 	/* Then we try a GladeWidget */
 	if (gwidget) 
 	{
-		retval = glade_widget_event (gwidget, event);
+		g_signal_emit_by_name (layout, "widget-event",
+				       gwidget, event, &retval);
 
 		if (retval)
 			return retval;
@@ -848,6 +859,19 @@
 	return FALSE;
 }
 
+static gboolean
+glade_design_layout_widget_event_impl (GladeProject *project,
+				       GladeWidget *gwidget,
+				       GdkEvent *event)
+{
+
+	if (glade_widget_event (gwidget, event))
+		return GLADE_WIDGET_EVENT_STOP_EMISSION |
+			GLADE_WIDGET_EVENT_RETURN_TRUE;
+	else
+		return 0;
+}
+
 static void
 glade_design_layout_init (GladeDesignLayout *layout)
 {
@@ -899,6 +923,36 @@
 	widget_class->size_request          = glade_design_layout_size_request;
 	widget_class->size_allocate         = glade_design_layout_size_allocate;
 
+	klass->widget_event          = glade_design_layout_widget_event_impl;
+
+	/**
+	 * GladeDesignLayout::widget-event:
+	 * @glade_design_layout: the #GladeDesignLayout containing the #GladeWidget.
+	 * @signal_editor: the #GladeWidget which received the signal.
+	 * @event: the #GdkEvent
+	 *
+	 * Emitted when a widget event received.
+	 * Connect before the default handler to block glade logic,
+	 * such as selecting or resizing, by returning #GLADE_WIDGET_EVENT_STOP_EMISSION.
+	 * If you want to handle the event after it passed the glade logic,
+	 * but before it reaches the widget, you should connect after the default handler.
+	 *
+	 * Returns: #GLADE_WIDGET_EVENT_STOP_EMISSION flag to abort futher emission of the signal.
+	 * #GLADE_WIDGET_EVENT_RETURN_TRUE flag in the last handler
+	 * to stop propagating of the event to the appropriate widget.
+	 */
+	glade_design_layout_signals[WIDGET_EVENT] =
+		g_signal_new ("widget-event",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GladeDesignLayoutClass, widget_event),
+			      glade_integer_handled_accumulator, NULL,
+			      glade_marshal_INT__OBJECT_BOXED,
+			      G_TYPE_INT,
+			      2,
+			      GLADE_TYPE_WIDGET,
+			      GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+
 	g_type_class_add_private (object_class, sizeof (GladeDesignLayoutPrivate));
 }
 

Modified: trunk/gladeui/glade-design-layout.h
==============================================================================
--- trunk/gladeui/glade-design-layout.h	(original)
+++ trunk/gladeui/glade-design-layout.h	Tue Jan 20 22:25:11 2009
@@ -40,6 +40,12 @@
 typedef struct _GladeDesignLayoutPrivate  GladeDesignLayoutPrivate;
 typedef struct _GladeDesignLayoutClass    GladeDesignLayoutClass;
 
+enum
+{
+	GLADE_WIDGET_EVENT_STOP_EMISSION   = 1 << 0,
+	GLADE_WIDGET_EVENT_RETURN_TRUE     = 1 << 1
+};
+
 struct _GladeDesignLayout
 {
 	GtkBin parent_instance;
@@ -50,6 +56,9 @@
 struct _GladeDesignLayoutClass
 {
 	GtkBinClass parent_class;
+	gboolean      (*widget_event)        (GladeProject *project,
+					      GladeWidget *gwidget,
+					      GdkEvent *event);
 
 };
 

Modified: trunk/gladeui/glade-editor.c
==============================================================================
--- trunk/gladeui/glade-editor.c	(original)
+++ trunk/gladeui/glade-editor.c	Tue Jan 20 22:25:11 2009
@@ -580,6 +580,18 @@
 	return editable;
 }
 
+void
+glade_editor_set_signal_editor (GladeEditor *editor, GladeSignalEditor *signal_editor)
+{
+	if (editor->signal_editor) {
+		gtk_container_remove (GTK_CONTAINER (editor->page_signals),
+		                      glade_signal_editor_get_widget (editor->signal_editor));
+	}
+	editor->signal_editor = signal_editor;
+	gtk_container_add (GTK_CONTAINER (editor->page_signals),
+			    glade_signal_editor_get_widget (editor->signal_editor));
+}
+
 static void
 glade_editor_load_signal_page (GladeEditor *editor)
 {

Modified: trunk/gladeui/glade-editor.h
==============================================================================
--- trunk/gladeui/glade-editor.h	(original)
+++ trunk/gladeui/glade-editor.h	Tue Jan 20 22:25:11 2009
@@ -154,7 +154,7 @@
 					      const gchar *book,
 					      const gchar *page,
 					      const gchar *search);
-
+void glade_editor_set_signal_editor (GladeEditor *editor, GladeSignalEditor *signal_editor);
 
 G_END_DECLS
 

Modified: trunk/gladeui/glade-marshallers.list
==============================================================================
--- trunk/gladeui/glade-marshallers.list	(original)
+++ trunk/gladeui/glade-marshallers.list	Tue Jan 20 22:25:11 2009
@@ -14,4 +14,7 @@
 BOOLEAN:OBJECT,UINT
 BOOLEAN:OBJECT,OBJECT
 BOOLEAN:OBJECT,STRING
+BOOLEAN:STRING,STRING,STRING,BOXED
+BOOLEAN:STRING,BOXED,OBJECT
 STRING:OBJECT
+INT:OBJECT,BOXED

Modified: trunk/gladeui/glade-signal-editor.c
==============================================================================
--- trunk/gladeui/glade-signal-editor.c	(original)
+++ trunk/gladeui/glade-signal-editor.c	Tue Jan 20 22:25:11 2009
@@ -44,26 +44,35 @@
 #include "glade-signal-editor.h"
 #include "glade-editor.h"
 #include "glade-command.h"
+#include "glade-marshallers.h"
+#include "glade-accumulators.h"
 
 
 enum
 {
-	COLUMN_SIGNAL,
-	COLUMN_HANDLER,
-	COLUMN_AFTER,
-	COLUMN_USERDATA,
-	COLUMN_LOOKUP,
-
-	COLUMN_USERDATA_SLOT,
-	COLUMN_LOOKUP_VISIBLE,
-	COLUMN_AFTER_VISIBLE,
-	COLUMN_HANDLER_EDITABLE,
-	COLUMN_USERDATA_EDITABLE,
-	COLUMN_SLOT, /* if this row contains a "<Type...>" label */
-	COLUMN_BOLD,
-	NUM_COLUMNS
+	HANDLER_EDITING_STARTED,
+	HANDLER_EDITING_DONE,
+	USERDATA_EDITING_STARTED,
+	USERDATA_EDITING_DONE,
+	LAST_SIGNAL
 };
 
+enum
+{
+	PROP_0,
+	PROP_HANDLER_COLUMN,
+	PROP_USERDATA_COLUMN,
+	PROP_HANDLER_COMPLETION,
+	PROP_USERDATA_COMPLETION,
+	PROP_HANDLER_RENDERER,
+	PROP_USERDATA_RENDERER
+};
+
+static guint glade_signal_editor_signals[LAST_SIGNAL] = {0};
+
+G_DEFINE_TYPE (GladeSignalEditor, glade_signal_editor, G_TYPE_OBJECT)
+
+
 #define HANDLER_DEFAULT  _("<Type here>")
 #define USERDATA_DEFAULT HANDLER_DEFAULT
 
@@ -88,17 +97,17 @@
 	/* get toggled iter */
 	gtk_tree_model_get_iter (model, &iter, path);
 	gtk_tree_model_get (model, &iter,
-			    COLUMN_SIGNAL,  &signal_name,
-			    COLUMN_HANDLER, &handler,
-			    COLUMN_USERDATA,&userdata,
-			    COLUMN_LOOKUP,  &lookup,
-			    COLUMN_AFTER,   &after, -1);
+			    GSE_COLUMN_SIGNAL,  &signal_name,
+			    GSE_COLUMN_HANDLER, &handler,
+			    GSE_COLUMN_USERDATA,&userdata,
+			    GSE_COLUMN_LOOKUP,  &lookup,
+			    GSE_COLUMN_AFTER,   &after, -1);
 	if (signal_name == NULL)
 	{
 		if (!gtk_tree_model_iter_parent (model, &iter_parent, &iter))
 			g_assert (FALSE);
 
-		gtk_tree_model_get (model, &iter_parent, COLUMN_SIGNAL, &signal_name, -1);
+		gtk_tree_model_get (model, &iter_parent, GSE_COLUMN_SIGNAL, &signal_name, -1);
 		g_assert (signal_name != NULL);
 	}
 
@@ -106,7 +115,7 @@
 	new_signal = glade_signal_new (signal_name, handler, userdata, !after);
 
 	glade_command_change_signal (editor->widget, old_signal, new_signal);
-	gtk_tree_store_set (GTK_TREE_STORE (model), &iter, COLUMN_AFTER, !after, -1);
+	gtk_tree_store_set (GTK_TREE_STORE (model), &iter, GSE_COLUMN_AFTER, !after, -1);
 
 	glade_signal_free (old_signal);
 	glade_signal_free (new_signal);
@@ -144,17 +153,17 @@
 	/* get toggled iter */
 	gtk_tree_model_get_iter (model, &iter, path);
 	gtk_tree_model_get (model, &iter,
-			    COLUMN_SIGNAL,  &signal_name,
-			    COLUMN_HANDLER, &handler,
-			    COLUMN_USERDATA,&userdata,
-			    COLUMN_LOOKUP,  &lookup,
-			    COLUMN_AFTER,   &after, -1);
+			    GSE_COLUMN_SIGNAL,  &signal_name,
+			    GSE_COLUMN_HANDLER, &handler,
+			    GSE_COLUMN_USERDATA,&userdata,
+			    GSE_COLUMN_LOOKUP,  &lookup,
+			    GSE_COLUMN_AFTER,   &after, -1);
 	if (signal_name == NULL)
 	{
 		if (!gtk_tree_model_iter_parent (model, &iter_parent, &iter))
 			g_assert (FALSE);
 
-		gtk_tree_model_get (model, &iter_parent, COLUMN_SIGNAL, &signal_name, -1);
+		gtk_tree_model_get (model, &iter_parent, GSE_COLUMN_SIGNAL, &signal_name, -1);
 		g_assert (signal_name != NULL);
 	}
 
@@ -162,7 +171,7 @@
 	new_signal = glade_signal_new (signal_name, handler, userdata, !lookup, after);
 
 	glade_command_change_signal (editor->widget, old_signal, new_signal);
-	gtk_tree_store_set (GTK_TREE_STORE (model), &iter, COLUMN_LOOKUP, !lookup, -1);
+	gtk_tree_store_set (GTK_TREE_STORE (model), &iter, GSE_COLUMN_LOOKUP, !lookup, -1);
 
 	glade_signal_free (old_signal);
 	glade_signal_free (new_signal);
@@ -201,93 +210,101 @@
 
 	gtk_tree_store_append (GTK_TREE_STORE (model), &iter_new_slot, iter_signal);
 	gtk_tree_store_set (GTK_TREE_STORE (model), &iter_new_slot,
-			    COLUMN_HANDLER,          _(HANDLER_DEFAULT),
-			    COLUMN_USERDATA,         _(USERDATA_DEFAULT),
-			    COLUMN_LOOKUP,           FALSE,
-			    COLUMN_LOOKUP_VISIBLE,   FALSE,
-			    COLUMN_HANDLER_EDITABLE, TRUE,
-			    COLUMN_USERDATA_EDITABLE,FALSE,
-			    COLUMN_AFTER,            FALSE,
-			    COLUMN_AFTER_VISIBLE,    FALSE,
-			    COLUMN_SLOT,             TRUE,
-			    COLUMN_USERDATA_SLOT,    TRUE,
+			    GSE_COLUMN_HANDLER,          _(HANDLER_DEFAULT),
+			    GSE_COLUMN_USERDATA,         _(USERDATA_DEFAULT),
+			    GSE_COLUMN_LOOKUP,           FALSE,
+			    GSE_COLUMN_LOOKUP_VISIBLE,   FALSE,
+			    GSE_COLUMN_HANDLER_EDITABLE, TRUE,
+			    GSE_COLUMN_USERDATA_EDITABLE,FALSE,
+			    GSE_COLUMN_AFTER,            FALSE,
+			    GSE_COLUMN_AFTER_VISIBLE,    FALSE,
+			    GSE_COLUMN_SLOT,             TRUE,
+			    GSE_COLUMN_USERDATA_SLOT,    TRUE,
 			    -1);
 	gtk_tree_model_iter_parent (model, &iter_class, iter_signal);
 
 	/* mark the signal & class name as bold */
-	gtk_tree_store_set (GTK_TREE_STORE (model), iter_signal, COLUMN_BOLD, TRUE, -1);
-	gtk_tree_store_set (GTK_TREE_STORE (model), &iter_class, COLUMN_BOLD, TRUE, -1);
+	gtk_tree_store_set (GTK_TREE_STORE (model), iter_signal, GSE_COLUMN_BOLD, TRUE, -1);
+	gtk_tree_store_set (GTK_TREE_STORE (model), &iter_class, GSE_COLUMN_BOLD, TRUE, -1);
 }
 
 static void
-remove_slot (GtkTreeModel *model, GtkTreeIter *iter)
+move_row (GtkTreeModel *model, GtkTreeIter *from, GtkTreeIter *to)
 {
-	GtkTreeIter iter_next;
-	GtkTreeIter iter_class;
-	GtkTreeIter iter_signal;
-	gboolean removing_top_signal_handler = TRUE;
-	char *signal_name;
+	gchar *handler;
+	gchar *userdata;
+	gboolean after;
+	gboolean slot;
+	gboolean visible;
+	gboolean userdata_slot;
+	gboolean handler_editable;
+	gboolean userdata_editable;
+	gboolean lookup;
+	gboolean lookup_visible;
+	gboolean bold;
 
-	gtk_tree_model_get (model, iter, COLUMN_SIGNAL, &signal_name, -1);
-	if (signal_name == NULL)
-	{
-		gtk_tree_model_iter_parent (model, &iter_signal, iter);
-		removing_top_signal_handler = FALSE;
-	}
-	else
-		iter_signal = *iter;
+	gtk_tree_model_get (model,                     from,
+			    GSE_COLUMN_HANDLER,           &handler,
+			    GSE_COLUMN_USERDATA,          &userdata,
+			    GSE_COLUMN_AFTER,             &after,
+			    GSE_COLUMN_SLOT,              &slot,
+			    GSE_COLUMN_AFTER_VISIBLE,     &visible,
+			    GSE_COLUMN_HANDLER_EDITABLE,  &handler_editable,
+			    GSE_COLUMN_USERDATA_EDITABLE, &userdata_editable,
+			    GSE_COLUMN_USERDATA_SLOT,     &userdata_slot,
+			    GSE_COLUMN_LOOKUP,            &lookup,
+			    GSE_COLUMN_LOOKUP_VISIBLE,    &lookup_visible,
+			    GSE_COLUMN_BOLD,              &bold,
+			    -1);
 
-	g_free (signal_name);
+	gtk_tree_store_set (GTK_TREE_STORE (model),   to,
+			    GSE_COLUMN_HANDLER,           handler,
+			    GSE_COLUMN_USERDATA,          userdata,
+			    GSE_COLUMN_AFTER,             after,
+			    GSE_COLUMN_SLOT,              slot,
+			    GSE_COLUMN_AFTER_VISIBLE,     visible,
+			    GSE_COLUMN_HANDLER_EDITABLE,  handler_editable,
+			    GSE_COLUMN_USERDATA_EDITABLE, userdata_editable,
+			    GSE_COLUMN_USERDATA_SLOT,     userdata_slot,
+			    GSE_COLUMN_LOOKUP,            lookup,
+			    GSE_COLUMN_LOOKUP_VISIBLE,    lookup_visible,
+			    GSE_COLUMN_BOLD,              &bold,
+			    -1);
+	g_free (handler);
+	g_free (userdata);
+}
+
+static void
+remove_slot (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *iter_signal)
+{
+	GtkTreeIter iter_class;
 
-	gtk_tree_model_iter_parent (model, &iter_class, &iter_signal);
+	gtk_tree_model_iter_parent (model, &iter_class, iter_signal);
 
 	/* special case for removing the handler of the first row */
-	if (removing_top_signal_handler)
-		gtk_tree_model_iter_nth_child (model, &iter_next, iter, 0);
-	else
+	if (iter == NULL)
 	{
-		iter_next = *iter;
-		gtk_tree_model_iter_next (model, &iter_next);
-	}
+		GtkTreeIter first_iter;
 
-	do
-	{
-		gchar *handler;
-		gboolean after;
-		gboolean slot;
-		gboolean visible;
-
-		gtk_tree_model_get (model,                &iter_next,
-				    COLUMN_HANDLER,       &handler,
-				    COLUMN_AFTER,         &after,
-				    COLUMN_SLOT,          &slot,
-				    COLUMN_AFTER_VISIBLE, &visible, -1);
-
-		gtk_tree_store_set (GTK_TREE_STORE (model), iter,
-				    COLUMN_HANDLER,         handler,
-				    COLUMN_AFTER,           after,
-				    COLUMN_SLOT,            slot,
-				    COLUMN_AFTER_VISIBLE,   visible, -1);
-		g_free (handler);
-
-		*iter = iter_next;
+		gtk_tree_model_iter_nth_child (model, &first_iter, iter_signal, 0);
+		move_row (model, &first_iter, iter_signal);
+		gtk_tree_store_remove (GTK_TREE_STORE (model), &first_iter);
 	}
-	while (gtk_tree_model_iter_next (model, &iter_next));
-
-	gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
+	else
+		gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
 
-	if (!gtk_tree_model_iter_has_child (model, &iter_signal))
+	if (!gtk_tree_model_iter_has_child (model, iter_signal))
 	{
 		/* mark the signal & class name as normal */
-		gtk_tree_store_set (GTK_TREE_STORE (model), &iter_signal,
-				    COLUMN_BOLD, FALSE, -1);
+		gtk_tree_store_set (GTK_TREE_STORE (model), iter_signal,
+				    GSE_COLUMN_BOLD, FALSE, -1);
 		gtk_tree_store_set (GTK_TREE_STORE (model), &iter_class,
-				    COLUMN_BOLD, FALSE, -1);
+				    GSE_COLUMN_BOLD, FALSE, -1);
 	}
 }
 
 static gboolean
-is_void_signal_handler (const gchar *signal_handler)
+is_void_handler (const gchar *signal_handler)
 {
 	return ( signal_handler == NULL ||
 		*signal_handler == 0    ||
@@ -295,274 +312,254 @@
 }
 
 static gboolean
-is_void_user_data (const gchar *user_data)
+is_void_userdata (const gchar *user_data)
 {
 	return ( user_data == NULL ||
 		*user_data == 0    ||
 		 g_utf8_collate (user_data, _(USERDATA_DEFAULT)) == 0);
 }
 
-static void
-glade_signal_editor_handler_cell_edited (GtkCellRendererText *cell,
-					 const gchar         *path_str,
-					 const gchar         *new_handler,
-					 gpointer             data)
+static gboolean
+glade_signal_editor_handler_editing_done_impl  (GladeSignalEditor *self,
+						gchar *signal_name,
+						gchar *old_handler,
+						gchar *new_handler,
+						GtkTreeIter *iter)
 {
-	GladeWidget *glade_widget = ((GladeSignalEditor*) data)->widget;
-	GtkTreeModel *model = GTK_TREE_MODEL (((GladeSignalEditor*) data)->model);
-	GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
-	GtkTreeIter iter;
+	GladeWidget *glade_widget = self->widget;
+	GtkTreeModel *model = GTK_TREE_MODEL (self->model);
+	gchar *tmp_signal_name;
+	gchar *userdata;
 	GtkTreeIter iter_signal;
-	gchar    *signal_name;
-	gchar    *old_handler;
-	gchar    *userdata;
-	gboolean  lookup;
 	gboolean  after;
-	gboolean  slot;
+	gboolean is_top_handler;
 
-	gtk_tree_model_get_iter (model, &iter, path);
-	gtk_tree_model_get (model,           &iter,
-			    COLUMN_SIGNAL,   &signal_name,
-			    COLUMN_HANDLER,  &old_handler,
-			    COLUMN_USERDATA, &userdata,
-			    COLUMN_LOOKUP,   &lookup,
-			    COLUMN_AFTER,    &after,
-			    COLUMN_SLOT,     &slot, -1);
+	gtk_tree_model_get (model,           iter,
+			    GSE_COLUMN_SIGNAL,   &tmp_signal_name,
+			    GSE_COLUMN_USERDATA, &userdata,
+			    GSE_COLUMN_AFTER,    &after, -1);
 
-	if (signal_name == NULL)
+	if (self->is_void_userdata (userdata))
 	{
-		if (!gtk_tree_model_iter_parent (model, &iter_signal, &iter))
-			g_assert (FALSE);
+		g_free (userdata);
+		userdata = NULL;
+	}
 
-		gtk_tree_model_get (model, &iter_signal, COLUMN_SIGNAL, &signal_name, -1);
-		g_assert (signal_name != NULL);
+	if (tmp_signal_name == NULL)
+	{
+		is_top_handler = FALSE;
+		gtk_tree_model_iter_parent (model, &iter_signal, iter);
 	}
 	else
-		iter_signal = iter;
-
-	/* false alarm */
-	if (slot && is_void_signal_handler(new_handler))
-		return;
+	{
+		is_top_handler = TRUE;
+		iter_signal = *iter;
+		g_free (tmp_signal_name);
+	}
 
 	/* we're adding a new handler */
-	if (slot && !is_void_signal_handler(new_handler))
+	if (old_handler == NULL && new_handler)
 	{
 		GladeSignal *new_signal = glade_signal_new (signal_name, new_handler,
 							    NULL, FALSE);
 		glade_command_add_signal (glade_widget, new_signal);
 		glade_signal_free (new_signal);
-		gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
-				    COLUMN_HANDLER,          new_handler,
-				    COLUMN_AFTER_VISIBLE,    TRUE,
-				    COLUMN_SLOT,             FALSE,
-				    COLUMN_USERDATA_EDITABLE,TRUE, -1);
+		gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+				    GSE_COLUMN_HANDLER,          new_handler,
+				    GSE_COLUMN_AFTER_VISIBLE,    TRUE,
+				    GSE_COLUMN_SLOT,             FALSE,
+				    GSE_COLUMN_USERDATA_EDITABLE,TRUE, -1);
 
 		/* append a <Type...> slot */
 		append_slot (model, &iter_signal);
 	}
 
 	/* we're removing a signal handler */
-	if (!slot && is_void_signal_handler(new_handler))
+	if (old_handler && new_handler == NULL)
 	{
-		GladeSignal *old_signal = 
-			glade_signal_new (signal_name, 
+		GladeSignal *old_signal =
+			glade_signal_new (signal_name,
 					  old_handler,
-					  is_void_user_data (userdata) ? NULL : userdata, 
+					  userdata, 
 					  after);
 		glade_command_remove_signal (glade_widget, old_signal);
 		glade_signal_free (old_signal);
 
 		gtk_tree_store_set
-			(GTK_TREE_STORE (model),          &iter,
-				 COLUMN_HANDLER,          _(HANDLER_DEFAULT),
-				 COLUMN_AFTER,            FALSE,
-				 COLUMN_USERDATA,         _(USERDATA_DEFAULT),
-				 COLUMN_LOOKUP,           FALSE,
-				 COLUMN_LOOKUP_VISIBLE,   FALSE,
-				 COLUMN_HANDLER_EDITABLE, TRUE,
-				 COLUMN_USERDATA_EDITABLE,FALSE,
-				 COLUMN_AFTER_VISIBLE,    FALSE,
-				 COLUMN_SLOT,             TRUE,
-				 COLUMN_USERDATA_SLOT,    TRUE,
+			(GTK_TREE_STORE (model),          iter,
+				 GSE_COLUMN_HANDLER,          _(HANDLER_DEFAULT),
+				 GSE_COLUMN_AFTER,            FALSE,
+				 GSE_COLUMN_USERDATA,         _(USERDATA_DEFAULT),
+				 GSE_COLUMN_LOOKUP,           FALSE,
+				 GSE_COLUMN_LOOKUP_VISIBLE,   FALSE,
+				 GSE_COLUMN_HANDLER_EDITABLE, TRUE,
+				 GSE_COLUMN_USERDATA_EDITABLE,FALSE,
+				 GSE_COLUMN_AFTER_VISIBLE,    FALSE,
+				 GSE_COLUMN_SLOT,             TRUE,
+				 GSE_COLUMN_USERDATA_SLOT,    TRUE,
 				 -1);
 
-		remove_slot (model, &iter);
+		remove_slot (model, is_top_handler ? NULL : iter, &iter_signal);
 	}
 
 	/* we're changing a signal handler */
-	if (!slot && !is_void_signal_handler(new_handler))
+	if (old_handler && new_handler)
 	{
 		GladeSignal *old_signal =
 			glade_signal_new
 			(signal_name,
 			 old_handler,
-			 is_void_user_data(userdata) ? NULL : userdata,
+			 userdata,
 			 after);
 		GladeSignal *new_signal =
 			glade_signal_new
 			(signal_name,
 			 new_handler,
-			 is_void_user_data(userdata) ? NULL : userdata,
+			 userdata,
 			 after);
 
-		glade_command_change_signal (glade_widget, old_signal, new_signal);
+		if (glade_signal_equal (old_signal, new_signal) == FALSE)
+			glade_command_change_signal (glade_widget, old_signal, new_signal);
 
 		glade_signal_free (old_signal);
 		glade_signal_free (new_signal);
 
-		gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
-				    COLUMN_HANDLER,       new_handler,
-				    COLUMN_AFTER_VISIBLE, TRUE,
-				    COLUMN_SLOT,          FALSE,
-				    COLUMN_USERDATA_EDITABLE,TRUE, -1);
+		gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+				    GSE_COLUMN_HANDLER,       new_handler,
+				    GSE_COLUMN_AFTER_VISIBLE, TRUE,
+				    GSE_COLUMN_SLOT,          FALSE,
+				    GSE_COLUMN_USERDATA_EDITABLE,TRUE, -1);
 	}
 
-	gtk_tree_path_free (path);
-	g_free (signal_name);
-	g_free (old_handler);
 	g_free (userdata);
+
+	return FALSE;
 }
 
-static void
-glade_signal_editor_construct_handler_store (GladeSignalEditor *editor)
+static gboolean
+glade_signal_editor_userdata_editing_done_impl (GladeSignalEditor *self,
+						gchar *signal_name,
+						gchar *old_userdata,
+						gchar *new_userdata,
+						GtkTreeIter *iter)
 {
-	const gchar *handlers[] = {"gtk_widget_show", 
-				   "gtk_widget_hide",
-				   "gtk_widget_grab_focus",
-				   "gtk_widget_destroy",
-				   "gtk_true",
-				   "gtk_false",
-				   "gtk_main_quit",
-				   NULL};
-	GtkTreeIter iter, *iters = editor->iters;
-	GtkEntryCompletion *completion;
-	GtkListStore *store;
-	gint i;
-				   
-	store = gtk_list_store_new (1, G_TYPE_STRING);
-		
-	gtk_list_store_append (store, &iters[0]);
-	gtk_list_store_append (store, &iters[1]);
-		
-	for (i = 0; handlers[i]; i++)
+	GtkTreeModel *model = GTK_TREE_MODEL (self->model);
+	GladeWidget  *glade_widget = self->widget;
+	gchar *handler;
+	gboolean after;
+	GladeSignal *old_signal, *new_signal;
+
+	gtk_tree_model_get (model,           iter,
+			    GSE_COLUMN_HANDLER,  &handler,
+			    GSE_COLUMN_AFTER,    &after, -1);
+
+	/* We are removing userdata */
+	if (new_userdata == NULL)
 	{
-		gtk_list_store_append (store, &iter);
-		gtk_list_store_set (store, &iter, 0, handlers[i], -1);
+		gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+				    GSE_COLUMN_USERDATA_SLOT,  TRUE,
+				    GSE_COLUMN_USERDATA,       _(USERDATA_DEFAULT),
+				    GSE_COLUMN_LOOKUP,         FALSE,
+				    GSE_COLUMN_LOOKUP_VISIBLE, FALSE, -1);
 	}
-	
-	completion = gtk_entry_completion_new ();
-	gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (store));
-	gtk_entry_completion_set_text_column (completion, 0);
-	gtk_entry_completion_set_inline_completion (completion, TRUE);
-	gtk_entry_completion_set_popup_completion (completion, FALSE);
-	
-	editor->handler_store = store;
-	editor->completion = completion;
-}
-
-static void
-glade_signal_editor_handler_store_update (GladeSignalEditor *editor,
-					  const gchar *path)
-{
-	GtkTreeModel *model = GTK_TREE_MODEL (editor->model);
-	GtkListStore *store = editor->handler_store;
-	GtkTreeIter iter, *iters = editor->iters;
-	gchar *handler, *signal, *name;
-	
-	name = (gchar *) glade_widget_get_name (editor->widget);
-		
-	if (gtk_tree_model_get_iter_from_string (model, &iter, path))
+	else
 	{
-		gtk_tree_model_get (model, &iter, COLUMN_SIGNAL, &signal, -1);
-		if (signal) glade_util_replace (signal, '-', '_');
-		else return;
+		gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+			    GSE_COLUMN_USERDATA_SLOT,  FALSE,
+			    GSE_COLUMN_USERDATA,       new_userdata,
+			    GSE_COLUMN_LOOKUP_VISIBLE, TRUE,
+			    -1);
 	}
-	else return;
 
-	handler = g_strdup_printf ("on_%s_%s", name, signal);
-	gtk_list_store_set (store, &iters[0], 0, handler, -1);
-	g_free (handler);
+	old_signal = glade_signal_new (signal_name, handler, old_userdata, after);
+
+	new_signal = glade_signal_new (signal_name, handler, new_userdata, after);
+
+	if (glade_signal_equal (old_signal, new_signal) == FALSE)
+		glade_command_change_signal (glade_widget, old_signal, new_signal);
+
+	glade_signal_free (old_signal);
+	glade_signal_free (new_signal);
 
-	handler = g_strdup_printf ("%s_%s_cb", name, signal);
-	gtk_list_store_set (store, &iters[1], 0, handler, -1);
 	g_free (handler);
-	
-	g_free (signal);
+	return FALSE;
 }
 
-static void
-glade_signal_editor_editing_started (GtkEntry *entry, gboolean handler)
+static gchar *
+glade_signal_editor_get_signal_name (GtkTreeModel *model, GtkTreeIter *iter)
 {
-	const gchar *text = gtk_entry_get_text (entry);
-	
-	if ((handler) ? is_void_signal_handler (text) : is_void_user_data (text))
-		gtk_entry_set_text (entry, "");
-}
+	gchar *signal_name;
+	gtk_tree_model_get (model,           iter,
+			    GSE_COLUMN_SIGNAL,   &signal_name,
+			    -1);
+	if (signal_name == NULL)
+	{
+		GtkTreeIter iter_signal;
 
-static void
-glade_signal_editor_handler_editing_started (GtkCellRenderer *cell,
-					     GtkCellEditable *editable,
-					     const gchar *path,
-					     GladeSignalEditor *editor)
-{
-	GtkEntry *entry;
-	
-	g_return_if_fail (GTK_IS_COMBO_BOX_ENTRY (editable));
-	entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (editable)));
-	
-	glade_signal_editor_editing_started (entry, TRUE);
-	
-	glade_signal_editor_handler_store_update (editor, path);
-	
-	gtk_entry_set_completion (entry, editor->completion);
+		if (!gtk_tree_model_iter_parent (model, &iter_signal, iter))
+			g_assert (FALSE);
+
+		gtk_tree_model_get (model, &iter_signal, GSE_COLUMN_SIGNAL, &signal_name, -1);
+		g_assert (signal_name != NULL);
+	}
+
+	return signal_name;
 }
 
 static void
-glade_signal_editor_user_data_editing_started (GtkCellRenderer *cell,
-					       GtkCellEditable *editable,
-					       const gchar *path,
-					       GladeSignalEditor *editor)
+glade_signal_editor_column_cell_edited (const gchar *path_str,
+					const gchar *new_value,
+					gpointer     data,
+					gint         column,
+					guint        signal,
+					IsVoidFunc   is_void_callback)
 {
-	GtkEntry *entry;
-	GtkEntryCompletion *completion;
-	GtkListStore *store;
+	GladeSignalEditor* self = GLADE_SIGNAL_EDITOR (data);
+	GtkTreeModel *model = GTK_TREE_MODEL (self->model);
+	GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
 	GtkTreeIter iter;
-	GList *list;
+	gchar    *signal_name;
+	gchar    *old_value;
+	gboolean  handled;
 
-	g_return_if_fail (GTK_IS_ENTRY (editable));
-	entry = GTK_ENTRY (editable);
-	
-	g_return_if_fail (editor->widget != NULL);
-	
-	glade_signal_editor_editing_started (entry, FALSE);
-	
-	store = gtk_list_store_new (1, G_TYPE_STRING);
-	
-	for (list = (GList *) glade_project_get_objects (editor->widget->project);
-	     list && list->data;
-	     list = g_list_next (list))
+	g_return_if_fail (gtk_tree_model_get_iter (model, &iter, path));
+	gtk_tree_path_free (path);
+	gtk_tree_model_get (model,  &iter,
+			    column, &old_value,
+			    -1);
+
+	signal_name = glade_signal_editor_get_signal_name (model, &iter);
+
+	if (is_void_callback (new_value))
+		new_value = NULL;
+
+	if (is_void_callback (old_value))
 	{
-		GladeWidget *widget = glade_widget_get_from_gobject (list->data);
-		
-		if (widget)
-		{
-			gtk_list_store_append (store, &iter);
-			gtk_list_store_set (store, &iter, 0, widget->name, -1);
-		}
+		g_free (old_value);
+		old_value = NULL;
 	}
-	
-	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), 0,
-					      GTK_SORT_DESCENDING);
-	
-	completion = gtk_entry_completion_new ();
-	
-	gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (store));
-	gtk_entry_completion_set_text_column (completion, 0);	
-	gtk_entry_set_completion (entry, completion);
-	
-	/* Get rid of references */
-	g_object_unref (store);
-	g_object_unref (completion);
+
+	/* if not a false alarm */
+	if (old_value || new_value)
+		g_signal_emit (self, glade_signal_editor_signals[signal],
+			       0, signal_name, old_value, new_value, &iter, &handled);
+
+	g_free (signal_name);
+	g_free (old_value);
+}
+
+static void
+glade_signal_editor_handler_cell_edited (GtkCellRendererText *cell,
+					 const gchar         *path_str,
+					 const gchar         *new_handler,
+					 gpointer             data)
+{
+	GladeSignalEditor *editor = GLADE_SIGNAL_EDITOR (data);
+
+	glade_signal_editor_column_cell_edited (path_str, new_handler, data,
+						GSE_COLUMN_HANDLER,
+						HANDLER_EDITING_DONE,
+						editor->is_void_handler);
 }
 
 static void
@@ -571,78 +568,112 @@
 					  const gchar         *new_userdata,
 					  gpointer             data)
 {
-	GladeWidget  *glade_widget = ((GladeSignalEditor*) data)->widget;
-	GtkTreeModel *model = GTK_TREE_MODEL (((GladeSignalEditor*) data)->model);
-	GtkTreePath  *path = gtk_tree_path_new_from_string (path_str);
+	GladeSignalEditor *editor = GLADE_SIGNAL_EDITOR (data);
+
+	glade_signal_editor_column_cell_edited (path_str, new_userdata, data,
+						GSE_COLUMN_USERDATA,
+						USERDATA_EDITING_DONE,
+						editor->is_void_userdata);
+}
+
+static void
+glade_signal_editor_column_editing_started (GtkCellEditable *editable,
+					    const gchar *path_str,
+					    GladeSignalEditor *editor,
+					    guint signal)
+{
+	GtkTreeModel *model = GTK_TREE_MODEL (editor->model);
+	GtkTreePath *path;
 	GtkTreeIter iter;
-	GtkTreeIter iter_signal;
-	GladeSignal *old_signal, *new_signal;
 	gchar *signal_name;
-	gchar *old_userdata;
-	gchar *handler;
-	gboolean after;
-	gboolean lookup;
-	
-	gtk_tree_model_get_iter (model, &iter, path);
-	gtk_tree_model_get (model,           &iter,
-			    COLUMN_SIGNAL,   &signal_name,
-			    COLUMN_HANDLER,  &handler,
-			    COLUMN_USERDATA, &old_userdata,
-			    COLUMN_LOOKUP,   &lookup,
-			    COLUMN_AFTER,    &after, -1);
+	gboolean handled;
 
-	if (signal_name == NULL)
-	{
-		if (!gtk_tree_model_iter_parent (model, &iter_signal, &iter))
-			g_assert (FALSE);
+	path = gtk_tree_path_new_from_string (path_str);
+	g_return_if_fail (gtk_tree_model_get_iter (model, &iter, path));
+	gtk_tree_path_free (path);
+	signal_name = glade_signal_editor_get_signal_name (model, &iter);
+	g_signal_emit (editor, glade_signal_editor_signals[signal], 0,
+		       signal_name, &iter, editable, &handled);
+	g_free (signal_name);
+}
 
-		gtk_tree_model_get (model, &iter_signal, COLUMN_SIGNAL, &signal_name, -1);
-		g_assert (signal_name != NULL);
-	}
-	else
-		iter_signal = iter;
+static void
+glade_signal_editor_handler_editing_started (GtkCellRenderer *cell,
+					     GtkCellEditable *editable,
+					     const gchar *path,
+					     GladeSignalEditor *editor)
+{
+	glade_signal_editor_column_editing_started (editable, path,
+						    editor, HANDLER_EDITING_STARTED);
+}
 
-	/* We are removing userdata */
-	if (is_void_user_data(new_userdata))
-	{
-		gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
-				    COLUMN_USERDATA_SLOT,  TRUE,
-				    COLUMN_USERDATA,       _(USERDATA_DEFAULT),
-				    COLUMN_LOOKUP,         FALSE,
-				    COLUMN_LOOKUP_VISIBLE, FALSE, -1);
-	}
+static void
+glade_signal_editor_userdata_editing_started (GtkCellRenderer *cell,
+					      GtkCellEditable *editable,
+					      const gchar *path,
+					      GladeSignalEditor *editor)
+{
+	glade_signal_editor_column_editing_started (editable, path,
+						    editor, USERDATA_EDITING_STARTED);
+}
+
+static void
+glade_signal_editor_signal_cell_data_func (GtkTreeViewColumn *tree_column,
+					   GtkCellRenderer *cell,
+					   GtkTreeModel *tree_model,
+					   GtkTreeIter *iter,
+					   gpointer data)
+{
+	gboolean bold;
+
+	gtk_tree_model_get (tree_model, iter, GSE_COLUMN_BOLD, &bold, -1);
+	if (bold)
+		g_object_set (G_OBJECT (cell), "weight", PANGO_WEIGHT_BOLD, NULL);
 	else
-	{
-		gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
-			    COLUMN_USERDATA_SLOT,  FALSE,
-			    COLUMN_USERDATA,       new_userdata,
-			    COLUMN_LOOKUP_VISIBLE, TRUE,
-			    -1);
-	}
+		g_object_set (G_OBJECT (cell), "weight", PANGO_WEIGHT_NORMAL, NULL);
+}
 
-	old_signal =
-		glade_signal_new
-		(signal_name, handler,
-		 is_void_user_data(old_userdata) ? NULL : old_userdata, after);
-
-	new_signal = 
-		glade_signal_new 
-		(signal_name, handler,
-		 is_void_user_data(new_userdata) ? NULL : new_userdata, after);
+static void
+glade_signal_editor_handler_cell_data_func (GtkTreeViewColumn *tree_column,
+					    GtkCellRenderer *cell,
+					    GtkTreeModel *tree_model,
+					    GtkTreeIter *iter,
+					    gpointer data)
+{
+	gboolean slot;
 
-	if (glade_signal_equal (old_signal, new_signal) == FALSE)
-		glade_command_change_signal (glade_widget, old_signal, new_signal);
-	
-	glade_signal_free (old_signal);
-	glade_signal_free (new_signal);
+	gtk_tree_model_get (tree_model, iter, GSE_COLUMN_SLOT, &slot, -1);
+	if (slot)
+		g_object_set (G_OBJECT (cell),
+			      "style", PANGO_STYLE_ITALIC,
+			      "foreground", "Gray", NULL);
+	else
+		g_object_set (G_OBJECT (cell),
+			      "style", PANGO_STYLE_NORMAL,
+			      "foreground", NULL, NULL);
+}
 
-	gtk_tree_path_free (path);
-	g_free (signal_name);
-	g_free (handler);
-	g_free (old_userdata);
+static void
+glade_signal_editor_userdata_cell_data_func (GtkTreeViewColumn *tree_column,
+					     GtkCellRenderer *cell,
+					     GtkTreeModel *tree_model,
+					     GtkTreeIter *iter,
+					     gpointer data)
+{
+	gboolean userdata_slot;
+
+	gtk_tree_model_get (tree_model, iter, GSE_COLUMN_USERDATA_SLOT, &userdata_slot, -1);
+	if (userdata_slot)
+		g_object_set (G_OBJECT (cell),
+			      "style", PANGO_STYLE_ITALIC,
+			      "foreground", "Gray", NULL);
+	else
+		g_object_set (G_OBJECT (cell),
+			      "style", PANGO_STYLE_NORMAL,
+			      "foreground", NULL, NULL);
 }
 
-static GtkWidget *
+void
 glade_signal_editor_construct_signals_list (GladeSignalEditor *editor)
 {
 	GtkTreeView *view;
@@ -652,7 +683,7 @@
 	GtkTreeModel *model;
 
 	editor->model = gtk_tree_store_new
-		(NUM_COLUMNS,
+		(GSE_NUM_COLUMNS,
 		 G_TYPE_STRING,   /* Signal  value      */
 		 G_TYPE_STRING,   /* Handler value      */
 		 G_TYPE_BOOLEAN,  /* After   value      */
@@ -677,63 +708,80 @@
 	/* the view now holds a reference, we can get rid of our own */
 	g_object_unref (G_OBJECT (editor->model));
 
-	/* Contruct handler model */
-	glade_signal_editor_construct_handler_store (editor);
-
 	/************************ signal column ************************/
  	renderer = gtk_cell_renderer_text_new ();
-	g_object_set (G_OBJECT (renderer), "weight", PANGO_WEIGHT_BOLD, NULL); 
 	column = gtk_tree_view_column_new_with_attributes
-		(_("Signal"), renderer, "text", COLUMN_SIGNAL, "weight-set", COLUMN_BOLD, NULL);
+		(_("Signal"), renderer, "text", GSE_COLUMN_SIGNAL, NULL);
+	gtk_tree_view_column_set_cell_data_func (column, renderer,
+						 glade_signal_editor_signal_cell_data_func,
+						 NULL, NULL);
  	gtk_tree_view_append_column (view, column);
 
 	/************************ handler column ************************/
- 	renderer = gtk_cell_renderer_combo_new ();
-	g_object_set (G_OBJECT (renderer),
-		      "style", PANGO_STYLE_ITALIC,
-		      "foreground", "Gray",
-		      "model", GTK_TREE_MODEL (editor->handler_store),
-		      "text-column", 0,
-		      NULL);
-	
-	g_signal_connect (renderer, "edited",
+ 	if (!editor->handler_store)
+			editor->handler_store = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
+
+	if (!editor->handler_renderer)
+ 	{
+ 		editor->handler_renderer = gtk_cell_renderer_combo_new ();
+		g_object_set (G_OBJECT (editor->handler_renderer),
+			      "model", editor->handler_store,
+			      "text-column", 0,
+			      NULL);
+	}
+
+	g_signal_connect (editor->handler_renderer, "edited",
 			  G_CALLBACK (glade_signal_editor_handler_cell_edited), editor);
 
-	g_signal_connect (renderer, "editing-started",
+	g_signal_connect (editor->handler_renderer, "editing-started",
 			  G_CALLBACK (glade_signal_editor_handler_editing_started),
 			  editor);
 
-	column = gtk_tree_view_column_new_with_attributes
-		(_("Handler"),     renderer,
-		 "text",           COLUMN_HANDLER,
-		 "style_set",      COLUMN_SLOT,
-		 "foreground_set", COLUMN_SLOT,
-		 "editable",       COLUMN_HANDLER_EDITABLE, NULL);
+	if (!editor->handler_column)
+	{
+		editor->handler_column = gtk_tree_view_column_new_with_attributes
+			(_("Handler"),     editor->handler_renderer,
+			 "text",           GSE_COLUMN_HANDLER,
+			 "editable",       GSE_COLUMN_HANDLER_EDITABLE, NULL);
+
+		gtk_tree_view_column_set_cell_data_func (editor->handler_column, editor->handler_renderer,
+							 glade_signal_editor_handler_cell_data_func,
+							 NULL, NULL);
+	}
 
- 	gtk_tree_view_append_column (view, column);
+ 	gtk_tree_view_append_column (view, editor->handler_column);
 
 	/************************ userdata column ************************/
- 	renderer = gtk_cell_renderer_text_new ();
-	g_object_set (G_OBJECT (renderer),
-		      "style", PANGO_STYLE_ITALIC,
-		      "foreground", "Gray", NULL);
+ 	if (!editor->userdata_renderer)
+ 	{
+ 		editor->userdata_renderer = gtk_cell_renderer_text_new ();
+	}
+			      
+	if (!editor->userdata_store)
+		editor->userdata_store = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
 
-	g_signal_connect (renderer, "edited",
+	g_signal_connect (editor->userdata_renderer, "edited",
 			  G_CALLBACK (glade_signal_editor_userdata_cell_edited), editor);
-	
-	g_signal_connect (renderer, "editing-started",
-			  G_CALLBACK (glade_signal_editor_user_data_editing_started),
+
+	g_signal_connect (editor->userdata_renderer, "editing-started",
+			  G_CALLBACK (glade_signal_editor_userdata_editing_started),
 			  editor);
-	
-	column = gtk_tree_view_column_new_with_attributes
-		(_("User data"), renderer,
-		 "text",           COLUMN_USERDATA,
-		 "style_set",      COLUMN_USERDATA_SLOT,
-		 "foreground_set", COLUMN_USERDATA_SLOT,
-		 "editable",       COLUMN_USERDATA_EDITABLE, NULL);
 
- 	gtk_tree_view_append_column (view, column);
-	
+	if (!editor->userdata_column)
+	{
+		editor->userdata_column =
+			gtk_tree_view_column_new_with_attributes
+				(_("User data"), editor->userdata_renderer,
+				 "text",           GSE_COLUMN_USERDATA,
+				 "editable",       GSE_COLUMN_USERDATA_EDITABLE, NULL);
+
+		gtk_tree_view_column_set_cell_data_func (editor->userdata_column, editor->userdata_renderer,
+							 glade_signal_editor_userdata_cell_data_func,
+							 NULL, NULL);
+	}
+
+ 	gtk_tree_view_append_column (view, editor->userdata_column);
+
 #if LOOKUP_COLUMN
 	/************************ lookup column ************************/
  	renderer = gtk_cell_renderer_toggle_new ();
@@ -741,8 +789,8 @@
 			  G_CALLBACK (glade_signal_editor_lookup_toggled), editor);
 	column = gtk_tree_view_column_new_with_attributes
 		(_("Lookup"), renderer,
-		 "active",  COLUMN_LOOKUP,
-		 "visible", COLUMN_LOOKUP_VISIBLE, NULL);
+		 "active",  GSE_COLUMN_LOOKUP,
+		 "visible", GSE_COLUMN_LOOKUP_VISIBLE, NULL);
 
  	gtk_tree_view_append_column (view, column);
 #endif
@@ -752,18 +800,26 @@
 			  G_CALLBACK (glade_signal_editor_after_toggled), editor);
  	column = gtk_tree_view_column_new_with_attributes
 		(_("After"), renderer,
-		 "active",  COLUMN_AFTER,
-		 "visible", COLUMN_AFTER_VISIBLE, NULL);
+		 "active",  GSE_COLUMN_AFTER,
+		 "visible", GSE_COLUMN_AFTER_VISIBLE, NULL);
  	gtk_tree_view_append_column (view, column);
 
-	return view_widget;
+	editor->signals_list = view_widget;
 }
 
-static void
-glade_signal_editor_construct (GladeSignalEditor *editor)
+static GObject*
+glade_signal_editor_constructor (GType                  type,
+				 guint                  n_construct_properties,
+				 GObjectConstructParam *construct_properties)
 {
 	GtkWidget *vbox;
 	GtkWidget *scroll;
+	GladeSignalEditor *editor;
+	GObject *retval;
+
+	retval = G_OBJECT_CLASS (glade_signal_editor_parent_class)->constructor
+		(type, n_construct_properties, construct_properties);
+	editor = GLADE_SIGNAL_EDITOR (retval);
 
 	vbox = gtk_vbox_new (FALSE, 0);
 	editor->main_window = vbox;
@@ -775,12 +831,15 @@
 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
 					     GTK_SHADOW_IN);
 
-	editor->signals_list = glade_signal_editor_construct_signals_list (editor);
+	g_signal_emit_by_name (glade_app_get(), "signal-editor-created", retval);
+
 	gtk_container_add (GTK_CONTAINER (scroll), editor->signals_list);
 
 	gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
 
 	gtk_widget_show_all (editor->main_window);
+
+	return retval;
 }
 
 /**
@@ -795,7 +854,7 @@
 {
 	g_return_val_if_fail (GLADE_IS_SIGNAL_EDITOR (editor), NULL);
 	g_return_val_if_fail (GTK_IS_WIDGET (editor->main_window), NULL);
-	
+
 	return editor->main_window;
 }
 
@@ -810,11 +869,10 @@
 {
 	GladeSignalEditor *signal_editor;
 
-	signal_editor = g_new0 (GladeSignalEditor, 1);
-
-	glade_signal_editor_construct (signal_editor);
+	signal_editor = GLADE_SIGNAL_EDITOR (g_object_new (GLADE_TYPE_SIGNAL_EDITOR,
+	                                                   NULL, NULL));
 	signal_editor->editor = editor;
-	
+
 	return signal_editor;
 }
 
@@ -825,7 +883,7 @@
  *
  * TODO: write me
  */
-void 
+void
 glade_signal_editor_load_widget (GladeSignalEditor *editor,
 				 GladeWidget *widget)
 {
@@ -853,19 +911,19 @@
 	for (list = editor->adaptor->signals; list; list = list->next)
 	{
 		GladeSignalClass *signal = (GladeSignalClass *) list->data;
-  
+
 		/* Add class name that this signal belongs to.
 		 */
 		if (strcmp(last_type, signal->type))
 		{
 			gtk_tree_store_append (editor->model, &parent_class, NULL);
 			gtk_tree_store_set    (editor->model,          &parent_class,
-					       COLUMN_SIGNAL,           signal->type,
-					       COLUMN_AFTER_VISIBLE,    FALSE,
-					       COLUMN_HANDLER_EDITABLE, FALSE,
-					       COLUMN_USERDATA_EDITABLE,FALSE,
-					       COLUMN_SLOT,             FALSE,
-					       COLUMN_BOLD,             FALSE, -1);
+					       GSE_COLUMN_SIGNAL,           signal->type,
+					       GSE_COLUMN_AFTER_VISIBLE,    FALSE,
+					       GSE_COLUMN_HANDLER_EDITABLE, FALSE,
+					       GSE_COLUMN_USERDATA_EDITABLE,FALSE,
+					       GSE_COLUMN_SLOT,             FALSE,
+					       GSE_COLUMN_BOLD,             FALSE, -1);
 			last_type = signal->type;
 		}
 
@@ -876,17 +934,17 @@
 		{
 			gtk_tree_store_set
 				(editor->model,          &parent_signal,
-				 COLUMN_SIGNAL,           signal->name,
-				 COLUMN_HANDLER,          _(HANDLER_DEFAULT),
-				 COLUMN_AFTER,            FALSE,
-				 COLUMN_USERDATA,         _(USERDATA_DEFAULT),
-				 COLUMN_LOOKUP,           FALSE,
-				 COLUMN_LOOKUP_VISIBLE,   FALSE,
-				 COLUMN_HANDLER_EDITABLE, TRUE,
-				 COLUMN_USERDATA_EDITABLE,FALSE,
-				 COLUMN_AFTER_VISIBLE,    FALSE,
-				 COLUMN_SLOT,             TRUE,
-				 COLUMN_USERDATA_SLOT,    TRUE,
+				 GSE_COLUMN_SIGNAL,           signal->name,
+				 GSE_COLUMN_HANDLER,          _(HANDLER_DEFAULT),
+				 GSE_COLUMN_AFTER,            FALSE,
+				 GSE_COLUMN_USERDATA,         _(USERDATA_DEFAULT),
+				 GSE_COLUMN_LOOKUP,           FALSE,
+				 GSE_COLUMN_LOOKUP_VISIBLE,   FALSE,
+				 GSE_COLUMN_HANDLER_EDITABLE, TRUE,
+				 GSE_COLUMN_USERDATA_EDITABLE,FALSE,
+				 GSE_COLUMN_AFTER_VISIBLE,    FALSE,
+				 GSE_COLUMN_SLOT,             TRUE,
+				 GSE_COLUMN_USERDATA_SLOT,    TRUE,
 				 -1);
 		}
 		else
@@ -896,9 +954,9 @@
 			GladeSignal *widget_signal =
 				(GladeSignal*) g_ptr_array_index (signals, 0);
 
-			/* mark the class of this signal as bold and expand it, 
+			/* mark the class of this signal as bold and expand it,
                          * as there is at least one signal with handler */
-			gtk_tree_store_set (editor->model, &parent_class, COLUMN_BOLD, TRUE, -1);
+			gtk_tree_store_set (editor->model, &parent_class, GSE_COLUMN_BOLD, TRUE, -1);
 			path_parent_class =
 				gtk_tree_model_get_path (GTK_TREE_MODEL (editor->model),
 							 &parent_class);
@@ -908,22 +966,22 @@
 
 			gtk_tree_store_set
 				(editor->model,            &parent_signal,
-				 COLUMN_SIGNAL,             signal->name,
-				 COLUMN_HANDLER,            widget_signal->handler,
-				 COLUMN_AFTER,              widget_signal->after,
-				 COLUMN_USERDATA,
+				 GSE_COLUMN_SIGNAL,             signal->name,
+				 GSE_COLUMN_HANDLER,            widget_signal->handler,
+				 GSE_COLUMN_AFTER,              widget_signal->after,
+				 GSE_COLUMN_USERDATA,
 				 widget_signal->userdata ?
 				 widget_signal->userdata : _(USERDATA_DEFAULT),
-				 COLUMN_LOOKUP,             FALSE/* widget_signal->lookup */,
-				 COLUMN_LOOKUP_VISIBLE,
+				 GSE_COLUMN_LOOKUP,             FALSE/* widget_signal->lookup */,
+				 GSE_COLUMN_LOOKUP_VISIBLE,
 				 widget_signal->userdata ?  TRUE : FALSE,
-				 COLUMN_AFTER_VISIBLE,      TRUE,
-				 COLUMN_HANDLER_EDITABLE,   TRUE,
-				 COLUMN_USERDATA_EDITABLE,  TRUE,
-				 COLUMN_SLOT,               FALSE,
-				 COLUMN_USERDATA_SLOT,
+				 GSE_COLUMN_AFTER_VISIBLE,      TRUE,
+				 GSE_COLUMN_HANDLER_EDITABLE,   TRUE,
+				 GSE_COLUMN_USERDATA_EDITABLE,  TRUE,
+				 GSE_COLUMN_SLOT,               FALSE,
+				 GSE_COLUMN_USERDATA_SLOT,
 				 widget_signal->userdata  ? FALSE : TRUE,
-				 COLUMN_BOLD,               TRUE, -1);
+				 GSE_COLUMN_BOLD,               TRUE, -1);
 
 			for (i = 1; i < signals->len; i++)
 			{
@@ -932,19 +990,19 @@
 
 				gtk_tree_store_set
 					(editor->model,            &iter,
-					 COLUMN_HANDLER,            widget_signal->handler,
-					 COLUMN_AFTER,              widget_signal->after,
-					 COLUMN_USERDATA,
+					 GSE_COLUMN_HANDLER,            widget_signal->handler,
+					 GSE_COLUMN_AFTER,              widget_signal->after,
+					 GSE_COLUMN_USERDATA,
 					 widget_signal->userdata  ?
 					 widget_signal->userdata : _(USERDATA_DEFAULT),
-					 COLUMN_LOOKUP,         FALSE/* widget_signal->lookup */,
-					 COLUMN_LOOKUP_VISIBLE,
+					 GSE_COLUMN_LOOKUP,         FALSE/* widget_signal->lookup */,
+					 GSE_COLUMN_LOOKUP_VISIBLE,
 					 widget_signal->userdata  ? TRUE : FALSE,
-					 COLUMN_AFTER_VISIBLE,      TRUE,
-					 COLUMN_HANDLER_EDITABLE,   TRUE,
-					 COLUMN_USERDATA_EDITABLE,  TRUE,
-					 COLUMN_SLOT,               FALSE,
-					 COLUMN_USERDATA_SLOT,
+					 GSE_COLUMN_AFTER_VISIBLE,      TRUE,
+					 GSE_COLUMN_HANDLER_EDITABLE,   TRUE,
+					 GSE_COLUMN_USERDATA_EDITABLE,  TRUE,
+					 GSE_COLUMN_SLOT,               FALSE,
+					 GSE_COLUMN_USERDATA_SLOT,
 					 widget_signal->userdata  ? FALSE : TRUE,
 					 -1);
 			}
@@ -953,16 +1011,16 @@
 			gtk_tree_store_append (editor->model, &iter, &parent_signal);
 			gtk_tree_store_set
 				(editor->model,          &iter,
-				 COLUMN_HANDLER,          _(HANDLER_DEFAULT),
-				 COLUMN_AFTER,            FALSE,
-				 COLUMN_USERDATA,         _(USERDATA_DEFAULT),
-				 COLUMN_LOOKUP,           FALSE,
-				 COLUMN_LOOKUP_VISIBLE,   FALSE,
-				 COLUMN_HANDLER_EDITABLE, TRUE,
-				 COLUMN_USERDATA_EDITABLE,FALSE,
-				 COLUMN_AFTER_VISIBLE,    FALSE,
-				 COLUMN_SLOT,             TRUE,
-				 COLUMN_USERDATA_SLOT,    TRUE, -1);
+				 GSE_COLUMN_HANDLER,          _(HANDLER_DEFAULT),
+				 GSE_COLUMN_AFTER,            FALSE,
+				 GSE_COLUMN_USERDATA,         _(USERDATA_DEFAULT),
+				 GSE_COLUMN_LOOKUP,           FALSE,
+				 GSE_COLUMN_LOOKUP_VISIBLE,   FALSE,
+				 GSE_COLUMN_HANDLER_EDITABLE, TRUE,
+				 GSE_COLUMN_USERDATA_EDITABLE,FALSE,
+				 GSE_COLUMN_AFTER_VISIBLE,    FALSE,
+				 GSE_COLUMN_SLOT,             TRUE,
+				 GSE_COLUMN_USERDATA_SLOT,    TRUE, -1);
 		}
 	}
 
@@ -970,3 +1028,396 @@
 	gtk_tree_view_expand_row (GTK_TREE_VIEW (editor->signals_list), path_first, FALSE);
 	gtk_tree_path_free (path_first);
 }
+
+static void
+glade_signal_editor_get_property  (GObject      *object,
+				   guint         prop_id,
+				   GValue *value,
+				   GParamSpec   *pspec)
+{
+	GladeSignalEditor *self = GLADE_SIGNAL_EDITOR (object);
+
+	switch (prop_id)
+	{
+	case PROP_HANDLER_COLUMN:
+		g_value_set_object (value, self->handler_column);
+		break;
+	case PROP_USERDATA_COLUMN:
+		g_value_set_object (value, self->userdata_column);
+		break;
+	case PROP_HANDLER_COMPLETION:
+		g_value_set_object (value, self->handler_store);
+		break;
+	case PROP_USERDATA_COMPLETION:
+		g_value_set_object (value, self->userdata_store);
+		break;
+	case PROP_HANDLER_RENDERER:
+		g_value_set_object (value, self->handler_renderer);
+		break;
+	case PROP_USERDATA_RENDERER:
+		g_value_set_object (value, self->userdata_renderer);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+glade_signal_editor_set_property  (GObject      *object,
+				   guint         prop_id,
+				   const GValue *value,
+				   GParamSpec   *pspec)
+{
+	GladeSignalEditor *self = GLADE_SIGNAL_EDITOR (object);
+
+	switch (prop_id)
+	{
+	case PROP_HANDLER_COLUMN:
+		self->handler_column = g_value_get_object (value);
+		break;
+	case PROP_USERDATA_COLUMN:
+		self->userdata_column = g_value_get_object (value);
+		break;
+	case PROP_HANDLER_COMPLETION:
+		self->handler_store = g_value_get_object (value);
+		break;
+	case PROP_USERDATA_COMPLETION:
+		self->userdata_store = g_value_get_object (value);
+		break;
+	case PROP_HANDLER_RENDERER:
+		self->handler_renderer = g_value_get_object (value);
+		break;
+	case PROP_USERDATA_RENDERER:
+		self->userdata_renderer = g_value_get_object (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+glade_signal_editor_finalize (GObject *object)
+{
+	GladeSignalEditor *self = GLADE_SIGNAL_EDITOR (object);
+
+	g_object_unref (self->handler_store);
+	g_object_unref (self->userdata_store);
+
+	G_OBJECT_CLASS (glade_signal_editor_parent_class)->finalize (object);
+}
+
+static void
+glade_signal_editor_init (GladeSignalEditor *self)
+{
+	self->is_void_handler = is_void_handler;
+	self->is_void_userdata = is_void_userdata;
+}
+
+static void
+glade_signal_editor_class_init (GladeSignalEditorClass *klass)
+{
+	GObjectClass *object_class;
+
+	glade_signal_editor_parent_class = g_type_class_peek_parent (klass);
+
+	object_class = G_OBJECT_CLASS (klass);
+
+	object_class->constructor = glade_signal_editor_constructor;
+	object_class->get_property = glade_signal_editor_get_property;
+	object_class->set_property = glade_signal_editor_set_property;
+	object_class->finalize = glade_signal_editor_finalize;
+	klass->handler_editing_done = glade_signal_editor_handler_editing_done_impl;
+	klass->userdata_editing_done = glade_signal_editor_userdata_editing_done_impl;
+	klass->handler_editing_started = NULL;
+	klass->userdata_editing_started = NULL;
+
+	g_object_class_install_property (object_class,
+	                                 PROP_HANDLER_COLUMN,
+	                                 g_param_spec_object ("handler-column",
+	                                                      NULL,
+	                                                      NULL,
+	                                                      GTK_TYPE_TREE_VIEW_COLUMN,
+	                                                      G_PARAM_READABLE |
+	                                                      G_PARAM_WRITABLE |
+	                                                      G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_USERDATA_COLUMN,
+	                                 g_param_spec_object ("userdata-column",
+	                                                      NULL,
+	                                                      NULL,
+	                                                      GTK_TYPE_TREE_VIEW_COLUMN,
+	                                                      G_PARAM_READABLE |
+	                                                      G_PARAM_WRITABLE |
+	                                                      G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_HANDLER_COMPLETION,
+	                                 g_param_spec_object ("handler-completion",
+	                                                      NULL,
+	                                                      NULL,
+	                                                      GTK_TYPE_TREE_MODEL,
+	                                                      G_PARAM_READABLE |
+	                                                      G_PARAM_WRITABLE |
+	                                                      G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_USERDATA_COMPLETION,
+	                                 g_param_spec_object ("userdata-completion",
+	                                                      NULL,
+	                                                      NULL,
+	                                                      GTK_TYPE_TREE_MODEL,
+	                                                      G_PARAM_READABLE |
+	                                                      G_PARAM_WRITABLE |
+	                                                      G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_HANDLER_RENDERER,
+	                                 g_param_spec_object ("handler-renderer",
+	                                                      NULL,
+	                                                      NULL,
+	                                                      GTK_TYPE_CELL_RENDERER,
+	                                                      G_PARAM_READABLE |
+	                                                      G_PARAM_WRITABLE |
+	                                                      G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_USERDATA_RENDERER,
+	                                 g_param_spec_object ("userdata-renderer",
+	                                                      NULL,
+	                                                      NULL,
+	                                                      GTK_TYPE_CELL_RENDERER,
+	                                                      G_PARAM_READABLE |
+	                                                      G_PARAM_WRITABLE |
+	                                                      G_PARAM_CONSTRUCT));	                                                      
+	/**
+	 * GladeSignalEditor::handler-editing-done:
+	 * @signal_editor: the #GladeSignalEditor which received the signal.
+	 * @signal_name: the name of the edited signal
+	 * @old_handler:
+	 * @new_handler:
+	 * @iter: the #GtkTreeIter of edited signal
+	 *
+	 * Emitted when editing of signal handler done.
+	 * You can cancel changes by returning FALSE before the default handler.
+	 */
+	glade_signal_editor_signals[HANDLER_EDITING_DONE] =
+		g_signal_new ("handler-editing-done",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GladeSignalEditorClass, handler_editing_done),
+			      glade_boolean_handled_accumulator, NULL,
+			      glade_marshal_BOOLEAN__STRING_STRING_STRING_BOXED,
+			      G_TYPE_BOOLEAN,
+			      4,
+			      G_TYPE_STRING, G_TYPE_STRING,
+			      G_TYPE_STRING, GTK_TYPE_TREE_ITER);
+
+	/**
+	 * GladeSignalEditor::userdata-editing-done:
+	 * @signal_editor: the #GladeSignalEditor which received the signal.
+	 * @signal_name: the name of the edited signal
+	 * @old_handler:
+	 * @new_handler:
+	 * @iter: the #GtkTreeIter of edited signal
+	 * 
+	 * Emitted when editing of signal user data done.
+	 * You can cancel changes by returning FALSE before the default handler.
+	 */
+	glade_signal_editor_signals[USERDATA_EDITING_DONE] =
+		g_signal_new ("userdata-editing-done",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GladeSignalEditorClass, userdata_editing_done),
+			      glade_boolean_handled_accumulator, NULL,
+			      glade_marshal_BOOLEAN__STRING_STRING_STRING_BOXED,
+			      G_TYPE_BOOLEAN,
+			      4,
+			      G_TYPE_STRING, G_TYPE_STRING,
+			      G_TYPE_STRING, GTK_TYPE_TREE_ITER);
+
+	/**
+	 * GladeSignalEditor::handler-editing-started:
+	 * @signal_editor: the #GladeSignalEditor which received the signal.
+	 * @signal_name: the name of the edited signal
+	 * @iter: the #GtkTreeIter of the edited signal
+	 * @editable: the #GtkCellEditable
+	 * 
+	 * Emitted when editing of signal handler started.
+	 * Used mainly for setting up completion.
+	 */
+	glade_signal_editor_signals[HANDLER_EDITING_STARTED] =
+		g_signal_new ("handler-editing-started",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GladeSignalEditorClass, handler_editing_started),
+			      glade_boolean_handled_accumulator, NULL,
+			      glade_marshal_BOOLEAN__STRING_BOXED_OBJECT,
+			      G_TYPE_BOOLEAN,
+			      3,
+			      G_TYPE_STRING, GTK_TYPE_TREE_ITER,
+			      GTK_TYPE_CELL_EDITABLE);
+
+	/**
+	 * GladeSignalEditor::userdata-editing-started:
+	 * @signal_editor: the #GladeSignalEditor which received the signal.
+	 * @signal_name: the name of the edited signal
+	 * @iter: the #GtkTreeIter of the edited signal
+	 * @editable: the #GtkCellEditable
+	 * 
+	 * Emitted when editing of signal user data started.
+	 * Used mainly for setting up completion.
+	 */
+	glade_signal_editor_signals[USERDATA_EDITING_STARTED] =
+		g_signal_new ("userdata-editing-started",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GladeSignalEditorClass, userdata_editing_started),
+			      glade_boolean_handled_accumulator, NULL,
+			      glade_marshal_BOOLEAN__STRING_BOXED_OBJECT,
+			      G_TYPE_BOOLEAN,
+			      3,
+			      G_TYPE_STRING, GTK_TYPE_TREE_ITER,
+			      GTK_TYPE_CELL_EDITABLE);
+}
+
+/* Default implementation of completion */
+
+static void
+glade_signal_editor_editing_started (GtkEntry *entry, IsVoidFunc callback)
+{
+	if (callback (gtk_entry_get_text (entry)))
+		gtk_entry_set_text (entry, "");
+}
+
+static void
+glade_signal_editor_handler_store_update (GladeSignalEditor *editor,
+					  const gchar *signal_name,
+					  GtkListStore *store)
+{
+	const gchar *handlers[] = {"gtk_widget_show",
+				   "gtk_widget_hide",
+				   "gtk_widget_grab_focus",
+				   "gtk_widget_destroy",
+				   "gtk_true",
+				   "gtk_false",
+				   "gtk_main_quit",
+				   NULL};
+
+	GtkTreeIter tmp_iter;
+	gint i;
+	gchar *handler, *signal, *name;
+
+	name = (gchar *) glade_widget_get_name (editor->widget);
+
+	signal = g_strdup (signal_name);
+	glade_util_replace (signal, '-', '_');
+
+	gtk_list_store_clear (store);
+
+	gtk_list_store_append (store, &tmp_iter);
+	handler = g_strdup_printf ("on_%s_%s", name, signal);
+	gtk_list_store_set (store, &tmp_iter, 0, handler, -1);
+	g_free (handler);
+
+	gtk_list_store_append (store, &tmp_iter);
+	handler = g_strdup_printf ("%s_%s_cb", name, signal);
+	gtk_list_store_set (store, &tmp_iter, 0, handler, -1);
+	g_free (handler);
+
+	g_free (signal);
+	for (i = 0; handlers[i]; i++)
+	{
+		gtk_list_store_append (store, &tmp_iter);
+		gtk_list_store_set (store, &tmp_iter, 0, handlers[i], -1);
+	}
+}
+
+gboolean
+glade_signal_editor_handler_editing_started_default_impl (GladeSignalEditor *editor,
+							  gchar *signal_name,
+							  GtkTreeIter *iter,
+							  GtkCellEditable *editable,
+							  gpointer user_data)
+{
+	
+	GtkEntry *entry;
+	GtkEntryCompletion *completion;
+	GtkTreeModel *completion_store = editor->handler_store;
+
+	g_return_val_if_fail (GTK_IS_BIN (editable), FALSE);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (completion_store), FALSE);
+
+	entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (editable)));
+
+	glade_signal_editor_editing_started (entry, editor->is_void_handler);
+
+	glade_signal_editor_handler_store_update (editor, signal_name,
+						  GTK_LIST_STORE (completion_store));
+
+	completion = gtk_entry_completion_new ();
+	gtk_entry_completion_set_text_column (completion, 0);
+	gtk_entry_completion_set_inline_completion (completion, TRUE);
+	gtk_entry_completion_set_popup_completion (completion, FALSE);
+	gtk_entry_completion_set_model (completion, completion_store);
+	gtk_entry_set_completion (entry, completion);
+
+	return FALSE;
+}
+
+static void
+glade_signal_editor_userdata_store_update (GladeSignalEditor *self,
+					   GtkListStore *store)
+{
+	GtkTreeIter tmp_iter;
+	GList *list;
+
+	gtk_list_store_clear (store);
+
+	for (list = (GList *) glade_project_get_objects (self->widget->project);
+	     list && list->data;
+	     list = g_list_next (list))
+	{
+		GladeWidget *widget = glade_widget_get_from_gobject (list->data);
+
+		if (widget)
+		{
+			gtk_list_store_append (store, &tmp_iter);
+			gtk_list_store_set (store, &tmp_iter, 0, widget->name, -1);
+		}
+	}
+
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), 0,
+					      GTK_SORT_DESCENDING);
+}
+
+gboolean
+glade_signal_editor_userdata_editing_started_default_impl (GladeSignalEditor *editor,
+							   gchar *signal_name,
+							   GtkTreeIter *iter,
+							   GtkCellEditable *editable,
+							   gpointer user_data)
+{
+	GtkEntry *entry;
+	GtkEntryCompletion *completion;
+	GtkTreeModel *completion_store = editor->userdata_store;
+
+	g_return_val_if_fail (editor->widget != NULL, FALSE);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (completion_store), FALSE);
+	g_return_val_if_fail (GTK_IS_ENTRY (editable), FALSE);
+
+	entry = GTK_ENTRY (editable);
+
+	glade_signal_editor_editing_started (entry, editor->is_void_handler);
+
+	glade_signal_editor_userdata_store_update (editor, GTK_LIST_STORE (completion_store));
+
+	completion = gtk_entry_completion_new ();
+	gtk_entry_completion_set_text_column (completion, 0);
+	gtk_entry_completion_set_model (completion, completion_store);
+	gtk_entry_set_completion (entry, completion);
+
+	return FALSE;
+}

Modified: trunk/gladeui/glade-signal-editor.h
==============================================================================
--- trunk/gladeui/glade-signal-editor.h	(original)
+++ trunk/gladeui/glade-signal-editor.h	Tue Jan 20 22:25:11 2009
@@ -6,18 +6,43 @@
 
 G_BEGIN_DECLS
 
-
-#define GLADE_SIGNAL_EDITOR(e) ((GladeSignalEditor *)e)
-#define GLADE_IS_SIGNAL_EDITOR(e) (e != NULL)
+#define GLADE_TYPE_SIGNAL_EDITOR            (glade_signal_editor_get_type ())
+#define GLADE_SIGNAL_EDITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_SIGNAL_EDITOR, GladeSignalEditor))
+#define GLADE_SIGNAL_EDITOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_SIGNAL_EDITOR, GladeSignalEditorClass))
+#define GLADE_IS_SIGNAL_EDITOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_SIGNAL_EDITOR))
+#define GLADE_IS_SIGNAL_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_SIGNAL_EDITOR))
+#define GLADE_SIGNAL_EDITOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GLADE_TYPE_SIGNAL_EDITOR, GladeSignalEditorClass))
 
 typedef struct _GladeSignalEditor  GladeSignalEditor;
+typedef struct _GladeSignalEditorClass  GladeSignalEditorClass;
+
+typedef gboolean (*IsVoidFunc) (const gchar *signal_handler);
 
+enum
+{
+	GSE_COLUMN_SIGNAL,
+	GSE_COLUMN_HANDLER,
+	GSE_COLUMN_AFTER,
+	GSE_COLUMN_USERDATA,
+	GSE_COLUMN_LOOKUP,
+
+	GSE_COLUMN_USERDATA_SLOT,
+	GSE_COLUMN_LOOKUP_VISIBLE,
+	GSE_COLUMN_AFTER_VISIBLE,
+	GSE_COLUMN_HANDLER_EDITABLE,
+	GSE_COLUMN_USERDATA_EDITABLE,
+	GSE_COLUMN_SLOT, /* if this row contains a "<Type...>" label */
+	GSE_COLUMN_BOLD,
+	GSE_NUM_COLUMNS
+};
 
 /* The GladeSignalEditor is used to house the signal editor interface and
  * associated functionality.
  */
 struct _GladeSignalEditor
 {
+	GObject parent;
+
 	GtkWidget *main_window;  /* A vbox where all the widgets are added */
 
 	GladeWidget *widget;
@@ -28,22 +53,62 @@
 	GtkWidget *signals_list;
 	GtkTreeStore *model;
 	GtkTreeView *tree_view;
-	
-	GtkListStore *handler_store; /* This store contains all the posible handler names */
-	GtkEntryCompletion *completion;
-	GtkTreeIter iters[2];
-};
 
+	GtkTreeModel *handler_store, *userdata_store;
+	GtkCellRenderer *handler_renderer, *userdata_renderer;
+	GtkTreeViewColumn *handler_column, *userdata_column;
+	IsVoidFunc is_void_handler, is_void_userdata;
+};
 
+struct _GladeSignalEditorClass
+{
+	GObjectClass parent_class;
 
-GtkWidget *glade_signal_editor_get_widget (GladeSignalEditor *editor);
+	gboolean (*handler_editing_done)   (GladeSignalEditor *self,
+						gchar *signal_name,
+						gchar *old_handler,
+						gchar *new_handler,
+						GtkTreeIter *iter);
+
+	gboolean (*userdata_editing_done)  (GladeSignalEditor *self,
+						gchar *signal_name,
+						gchar *old_userdata,
+						gchar *new_userdata,
+						GtkTreeIter *iter);
+
+	gboolean (*handler_editing_started)    (GladeSignalEditor *self,
+						gchar *signal_name,
+						GtkTreeIter *iter,
+						GtkCellEditable *editable);
+
+	gboolean (*userdata_editing_started)   (GladeSignalEditor *self,
+						gchar *signal_name,
+						GtkTreeIter *iter,
+						GtkCellEditable *editable);
+};
 
+GType glade_signal_editor_get_type (void) G_GNUC_CONST;
 
 GladeSignalEditor *glade_signal_editor_new (gpointer *editor);
 
+void glade_signal_editor_construct_signals_list (GladeSignalEditor *editor);
+
+GtkWidget *glade_signal_editor_get_widget (GladeSignalEditor *editor);
 
 void glade_signal_editor_load_widget (GladeSignalEditor *editor, GladeWidget *widget);
 
+gboolean
+glade_signal_editor_handler_editing_started_default_impl (GladeSignalEditor *editor,
+							  gchar *signal_name,
+							  GtkTreeIter *iter,
+							  GtkCellEditable *editable,
+							  gpointer user_data);
+gboolean
+glade_signal_editor_userdata_editing_started_default_impl (GladeSignalEditor *editor,
+							   gchar *signal_name,
+							   GtkTreeIter *iter,
+							   GtkCellEditable *editable,
+							   gpointer user_data);
 
 G_END_DECLS
 

Modified: trunk/plugins/gnome/glade-gnome.c
==============================================================================
--- trunk/plugins/gnome/glade-gnome.c	(original)
+++ trunk/plugins/gnome/glade-gnome.c	Tue Jan 20 22:25:11 2009
@@ -1605,7 +1605,9 @@
 			return TRUE;
 		}
         }
-        
+
+	g_warning ("Item not found in BonoboDock");
+	
         return FALSE;
 }
 
@@ -1638,41 +1640,44 @@
 	}
 	
 	wchild = GTK_WIDGET (child);
-	glade_gnome_bonobodockitem_get_props (dock, item, &placement, &band_num,
-					      &band_position, &offset);
 	
-	if (strcmp ("placement", property_name) == 0)
-		placement = g_value_get_enum (value);
-	else if (strcmp ("position", property_name) == 0)
-		band_position = g_value_get_int (value);
-	else if (strcmp ("band", property_name) == 0)
-		band_num = g_value_get_int (value);
-	else if (strcmp ("offset", property_name) == 0)
-		offset = g_value_get_int (value);
-	else
+	if (glade_gnome_bonobodockitem_get_props (dock, item, &placement, &band_num,
+						  &band_position, &offset))
 	{
-		g_warning ("No BonoboDock set packing property support for '%s'.", property_name);
-		return;
-	}
-	
-	if ((band = glade_gnome_bd_get_band (dock, wchild)))
-	{		
-		g_object_ref (child);
-		gtk_container_remove (GTK_CONTAINER (band), wchild);
-		
-		if (band->num_children == 0)
+		if (strcmp ("placement", property_name) == 0)
+			placement = g_value_get_enum (value);
+		else if (strcmp ("position", property_name) == 0)
+			band_position = g_value_get_int (value);
+		else if (strcmp ("band", property_name) == 0)
+			band_num = g_value_get_int (value);
+		else if (strcmp ("offset", property_name) == 0)
+			offset = g_value_get_int (value);
+		else
 		{
-			new_band = TRUE;
-			gtk_container_remove (GTK_CONTAINER (container), GTK_WIDGET(band));
+			g_warning ("No BonoboDock set packing property support for '%s'.", property_name);
+			return;
 		}
+	
+		if ((band = glade_gnome_bd_get_band (dock, wchild)))
+		{
+			g_object_ref (child);
+			gtk_container_remove (GTK_CONTAINER (band), wchild);
+		
+			if (band->num_children == 0)
+			{
+				new_band = TRUE;
+				gtk_container_remove (GTK_CONTAINER (container),
+						      GTK_WIDGET(band));
+			}
 		
-		bonobo_dock_add_item (dock, item, placement, band_num, 
-				      band_position, offset, new_band);
-		bonobo_dock_item_set_behavior (item, item->behavior);
-		g_object_unref (child);
+			bonobo_dock_add_item (dock, item, placement, band_num, 
+					      band_position, offset, new_band);
+			bonobo_dock_item_set_behavior (item, item->behavior);
+			g_object_unref (child);
+		}
+		else
+			g_warning ("BonoboDockItem's band not found.\n");
 	}
-	else
-		g_warning ("BonoboDockItem's band not found.\n");
 }
 
 void
@@ -1699,19 +1704,20 @@
 		return;
 	}
 	
-	glade_gnome_bonobodockitem_get_props (BONOBO_DOCK (container),
-					      BONOBO_DOCK_ITEM (child),
-					      &placement, &band_num,
-					      &band_position, &offset);
-	
-	if (strcmp ("placement", property_name) == 0)
-		g_value_set_enum (value, placement);
-	else if (strcmp ("position", property_name) == 0)
-		g_value_set_int (value, band_position);
-	else if (strcmp ("band", property_name) == 0)
-		g_value_set_int (value, band_num);
-	else if (strcmp ("offset", property_name) == 0)
-		g_value_set_int (value, offset);
+	if (glade_gnome_bonobodockitem_get_props (BONOBO_DOCK (container),
+						  BONOBO_DOCK_ITEM (child),
+						  &placement, &band_num,
+						  &band_position, &offset))
+	{	
+		if (strcmp ("placement", property_name) == 0)
+			g_value_set_enum (value, placement);
+		else if (strcmp ("position", property_name) == 0)
+			g_value_set_int (value, band_position);
+		else if (strcmp ("band", property_name) == 0)
+			g_value_set_int (value, band_num);
+		else if (strcmp ("offset", property_name) == 0)
+			g_value_set_int (value, offset);
+	}
 }
 
 void

Modified: trunk/src/glade-window.c
==============================================================================
--- trunk/src/glade-window.c	(original)
+++ trunk/src/glade-window.c	Tue Jan 20 22:25:11 2009
@@ -3045,6 +3045,16 @@
 	show_dock_first_time (window, DOCK_INSPECTOR, "DockInspector");
 	show_dock_first_time (window, DOCK_EDITOR, "DockEditor");
 
+	/* signal editor */
+	g_signal_connect (G_OBJECT (glade_app_get_editor()->signal_editor),
+	                  "handler-editing-started",
+	                  G_CALLBACK (glade_signal_editor_handler_editing_started_default_impl),
+	                  NULL);
+	g_signal_connect (G_OBJECT (glade_app_get_editor()->signal_editor),
+	                  "userdata-editing-started",
+	                  G_CALLBACK (glade_signal_editor_userdata_editing_started_default_impl),
+	                  NULL);
+
 	/* status bar */
 	priv->statusbar = gtk_statusbar_new ();
 	priv->statusbar_menu_context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (priv->statusbar),



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]