Hi Archit,

(I've cc'ed Joaquin since the attached patch is big and maybe the mail
will not reach the list)

Attached there is the current diff of my tree against cvs where I think
I've fixed this bug (along with some others and along with adding some
new ones ;) )

If you could verify/review the patch it would be great!

On Sun, 2003-06-01 at 03:07, Archit Baweja wrote:
> Well I had been testing my undo/redo code for cut/paste a lot, as I wrote it. 
> I haven't fixed it yet, but just thought I'd mention it to you guys. Try this 
> out
> 
> Create window
> Add a hbox
> Add a button
> Now cut and then paste 3 times the button
> Now keep doing undo
> When it is time to undo the first cut (thats the third time it is *supposed* to
> show up again), it crashes. 
> 

What I think is the problem is that every cut creates a new placeholder,
so when you undo the first cut what happens is that it tries to paste on
a placeholder which isn't there anymore.

The main fixes to this is in command.c where I ref the placeholders and
in glade_widget_replace_with_placeholder where I pass the placeholder
instead of always creating a new one. 

I'm sorry that I attached the whole diff containing other changes but
extracting only that one was a bit painful. The description of the other
changes follows below.
It also contains cleanups to project/placeholder/widget I already
submitted separately to the list.

glade-clipboard.[ch]:
* (cleanup) moved cut/copy logic to the corresponding functions in
command.c, as they were only called there and since makes code similar
to the create/delete commands. Renamed  clipboard_copy
clipboard_add_copy. Now the API for a clipboard are: add, add_copy and
remove.
* (bugfix) clipboard->curr was set to null when removing a widget, now
it is set to the first widget of the clipboard->widgets list

glade-command.c
* above explained changes to cut/paste
* cleanup/fix create/delete in ways similar to the cut/paste commands
* please check the finalize functions... is it ok to unref
unconditionally? (as create/delete already did)

glade-placeholder.c
* misc cleanups, in particular add g_return_of_fail to check the args of
the functions we expose as APIs

maybe there are also other minor changes which I don't remember ;)


Let me know what do you think!

ciao
        paolo

PS: to Joaquin: do these changes looks ok? Do you want me to split em up
for submission?

diff -upr gnome2/glade3/src/glade-clipboard.c glade3/src/glade-clipboard.c
--- gnome2/glade3/src/glade-clipboard.c	2003-05-24 17:41:46.000000000 +0200
+++ glade3/src/glade-clipboard.c	2003-06-02 14:28:27.000000000 +0200
@@ -29,7 +29,6 @@
 #include "glade-widget-class.h"
 #include "glade-placeholder.h"
 #include "glade-project.h"
-#include "glade-packing.h"
 
 static void
 glade_clipboard_class_init (GladeClipboardClass *klass)
@@ -96,10 +95,9 @@ glade_clipboard_new ()
  * @clipboard: 
  * @widget: 
  * 
- * Add a GladeWidget to the Clipboard. Basically has stuff common to 
- * Cut/Copy commands.
+ * Move a GladeWidget onto the Clipboard.
  **/
-static void
+void
 glade_clipboard_add (GladeClipboard *clipboard, GladeWidget *widget)
 {
 	/*
@@ -117,65 +115,14 @@ glade_clipboard_add (GladeClipboard *cli
 }
 
 /**
- * glade_clipboard_remove:
- * @clipboard: 
- * @widget: 
- * 
- * Remove a GladeWidget from the Clipboard
- **/
-static void
-glade_clipboard_remove (GladeClipboard *clipboard, GladeWidget *widget)
-{
-	clipboard->widgets = g_list_remove (clipboard->widgets, widget);
-	clipboard->curr = NULL;
-
-	/*
-	 * If there is a view present, update it.
-	 */
-	if (clipboard->view)
-		glade_clipboard_view_remove (GLADE_CLIPBOARD_VIEW (clipboard->view), widget);
-}
-
-/**
- * glade_clipboard_cut:
- * @clipboard: 
- * @widget: 
- * 
- * Cut a GladeWidget onto the Clipboard. 
- **/
-GladePlaceholder *
-glade_clipboard_cut (GladeClipboard *clipboard, GladeWidget *widget)
-{
-	GladePlaceholder *placeholder = NULL;
-
-	g_return_val_if_fail (GLADE_IS_CLIPBOARD (clipboard), NULL);
-	g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL);
-
-	glade_project_remove_widget (widget);
-
-	/*
-	 * We ref so that the widget and its children are not destroyed.
-	 */
-	gtk_widget_ref (GTK_WIDGET (widget->widget));
-	if (widget->parent)
-		placeholder = glade_widget_replace_with_placeholder (widget);
-	else
-		gtk_widget_hide (widget->widget);
-
-	glade_clipboard_add (clipboard, widget);
-
-	return placeholder;
-}
-
-/**
- * glade_clipboard_copy:
+ * glade_clipboard_add_copy:
  * @clipboard: 
  * @widget: 
  * 
- * Copy a GladeWidget onto the Clipboard. 
+ * Add a copy of a GladeWidget onto the Clipboard. 
  **/
 void
-glade_clipboard_copy (GladeClipboard *clipboard, GladeWidget *widget)
+glade_clipboard_add_copy (GladeClipboard *clipboard, GladeWidget *widget)
 {
 	GladeWidget *copy;
 
@@ -183,69 +130,33 @@ glade_clipboard_copy (GladeClipboard *cl
 	g_return_if_fail (GLADE_IS_WIDGET (widget));
 
 	copy = glade_widget_clone (widget);
-
 	glade_clipboard_add (clipboard, copy);
 }
 
 /**
- * glade_clipboard_paste:
+ * glade_clipboard_remove:
  * @clipboard: 
- * @placeholder: 
+ * @widget: 
  * 
- * Paste a GladeWidget from the Clipboard.
+ * Remove a GladeWidget from the Clipboard
  **/
 void
-glade_clipboard_paste (GladeClipboard *clipboard,
-		       GladePlaceholder *placeholder)
+glade_clipboard_remove (GladeClipboard *clipboard, GladeWidget *widget)
 {
-	GladeWidget *widget;
-	GladeWidget *parent;
-	GladeProject *project;
-
-	g_return_if_fail (GLADE_IS_CLIPBOARD (clipboard));
-
-	widget = clipboard->curr;
-
-	if (!widget)
-		return;
+	GList *list;
 
-	parent = glade_placeholder_get_parent (placeholder);
-
-	project = parent->project;
-
-	widget->name = glade_widget_new_name (project, widget->class);
-	widget->parent = parent;
-	glade_packing_add_properties (widget);
-	glade_project_add_widget (project, widget);
-
-	if (parent)
-		parent->children = g_list_prepend (parent->children, widget);
-
-	glade_widget_set_contents (widget);
-	glade_widget_connect_signals (widget);
-
-	/*
-	 * Toplevel widgets are not packed into other containers :-)
-	 */
-	if (!GLADE_WIDGET_IS_TOPLEVEL (widget)) {
-		/* Signal error, if placeholder not selected */
-		if (!placeholder) {
-			glade_util_ui_warn (_("Placeholder not selected!"));
-			return;
-		}
-
-		glade_placeholder_replace (placeholder, parent, widget);
-		glade_widget_set_default_packing_options (widget);
-	}
+	clipboard->widgets = g_list_remove (clipboard->widgets, widget);
 
-	glade_project_selection_set (widget, TRUE);
+	list = g_list_first (clipboard->widgets);
+	if (list != NULL)
+		clipboard->curr = GLADE_WIDGET (list->data);
+	else
+		clipboard->curr = NULL;
 
 	/*
-	 * This damned 'if' statement caused a 1 month delay.
+	 * If there is a view present, update it.
 	 */
-	if (GTK_IS_WIDGET (widget->widget))
-		gtk_widget_show_all (GTK_WIDGET (widget->widget));
-
-	glade_clipboard_remove (clipboard, widget);
+	if (clipboard->view)
+		glade_clipboard_view_remove (GLADE_CLIPBOARD_VIEW (clipboard->view), widget);
 }
 
diff -upr gnome2/glade3/src/glade-clipboard.h glade3/src/glade-clipboard.h
--- gnome2/glade3/src/glade-clipboard.h	2003-05-24 17:41:46.000000000 +0200
+++ glade3/src/glade-clipboard.h	2003-06-02 14:11:21.000000000 +0200
@@ -2,17 +2,21 @@
 #define __GLADE_CLIPBOARD_H__
 
 G_BEGIN_DECLS
+
 #define GLADE_TYPE_CLIPBOARD    (glade_clipboard_get_type ())
 #define GLADE_CLIPBOARD(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_CLIPBOARD, GladeClipboard))
 #define GLADE_IS_CLIPBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_CLIPBOARD))
+
 typedef struct _GladeClipboardClass GladeClipboardClass;
 
 struct _GladeClipboard {
 	GObject __parent__;
 
 	GList *widgets;		/* A list of GladeWidget's on the clipboard */
+
 	GladeWidget *curr;	/* The currently selected GladeWidget in the
-				   Clipboard */
+				 * Clipboard
+				 */
 
 	GtkWidget *view;	/* see glade-clipboard-view.c */
 };
@@ -23,14 +27,16 @@ struct _GladeClipboardClass {
 
 
 GType glade_clipboard_get_type ();
+
 GladeClipboard *glade_clipboard_new ();
 
-GladePlaceholder * glade_clipboard_cut    (GladeClipboard * clipboard,
-					   GladeWidget * widget);
-void               glade_clipboard_copy   (GladeClipboard * clipboard,
-					   GladeWidget * widget);
-void               glade_clipboard_paste  (GladeClipboard * clipboard,
-					   GladePlaceholder * placeholder);
+void glade_clipboard_add (GladeClipboard *clipboard, GladeWidget *widget);
+
+void glade_clipboard_add_copy (GladeClipboard *clipboard, GladeWidget *widget);
+
+void glade_clipboard_remove (GladeClipboard *clipboard, GladeWidget *widget);
+
 
 G_END_DECLS
+
 #endif				/* __GLADE_CLIPBOARD_H__ */
diff -upr gnome2/glade3/src/glade-command.c glade3/src/glade-command.c
--- gnome2/glade3/src/glade-command.c	2003-06-01 11:15:03.000000000 +0200
+++ glade3/src/glade-command.c	2003-06-02 17:04:17.000000000 +0200
@@ -29,6 +29,7 @@
 #include "glade-widget.h"
 #include "glade-widget-class.h"
 #include "glade-command.h"
+#include "glade-packing.h"
 #include "glade-property.h"
 #include "glade-debug.h"
 #include "glade-placeholder.h"
@@ -608,27 +609,20 @@ glade_command_create_execute (GladeComma
 	GladeWidget *widget = me->widget;
 	GladePlaceholder *placeholder = me->placeholder;
 
-	if (placeholder) {
-		if (widget->parent->class->placeholder_replace)
-			widget->parent->class->placeholder_replace (GTK_WIDGET (placeholder),
-								    widget->widget,
-								    widget->parent->widget);
-		glade_widget_set_default_packing_options (widget);
-		me->placeholder = NULL;
-	}
+	glade_project_add_widget (widget->project, widget, widget->parent);
+	glade_project_selection_set (widget, TRUE);
 
-	if (widget->parent)
-		widget->parent->children = g_list_prepend (widget->parent->children, widget);
+	if (!GLADE_WIDGET_IS_TOPLEVEL (widget)) {
+		gtk_widget_ref (GTK_WIDGET (placeholder));
 
-	glade_project_selection_clear (widget->project, FALSE);
-	glade_project_add_widget (widget->project, widget);
-
-	if (GTK_IS_WIDGET (widget->widget)) {
-		glade_project_selection_add (widget, TRUE);
-		gtk_widget_show (widget->widget);
+		glade_placeholder_replace_with_widget (placeholder, widget);
+		glade_widget_set_default_packing_options (widget);
 	}
 
-	return FALSE;
+	if (GTK_IS_WIDGET (widget->widget))
+		gtk_widget_show_all (widget->widget);
+
+	return TRUE;
 }
 
 static gboolean
@@ -638,19 +632,18 @@ glade_command_delete_execute (GladeComma
 
 	g_return_val_if_fail (widget != NULL, TRUE);
 
-	glade_project_selection_remove (widget, TRUE);
-	glade_project_remove_widget (widget);
-
 	if (widget->parent != NULL) {
+		/* We ref so that the widget and its children are not destroyed. */
 		gtk_widget_ref (widget->widget);
-		me->placeholder = glade_widget_replace_with_placeholder (widget);
-	} else {
-		me->placeholder = NULL;
+
+		me->placeholder = glade_widget_replace_with_placeholder (widget, me->placeholder);
 	}
 
 	gtk_widget_hide (widget->widget);
 
-	return FALSE;
+	glade_project_remove_widget (widget);
+
+	return TRUE;
 }
 
 /**
@@ -669,6 +662,7 @@ glade_command_create_delete_execute (Gla
 		retval = glade_command_delete_execute (me);
 
 	me->create = !me->create;
+
 	return retval;
 }
 
@@ -676,7 +670,10 @@ static void
 glade_command_create_delete_finalize (GObject *obj)
 {
 	GladeCommandCreateDelete *cmd = GLADE_COMMAND_CREATE_DELETE (obj);
+
+	g_object_unref (cmd->placeholder);
 	g_object_unref (cmd->widget);
+
         glade_command_finalize (obj);
 }
 
@@ -713,8 +710,8 @@ glade_command_create_delete_common (Glad
 
 	g_debug(("Pushing: %s\n", cmd->description));
 
-	glade_command_create_delete_execute (GLADE_COMMAND (me));
-	glade_command_push_undo(widget->project, GLADE_COMMAND (me));
+	if (glade_command_create_delete_execute (GLADE_COMMAND (me)));
+		glade_command_push_undo(widget->project, GLADE_COMMAND (me));
 }
 
 void
@@ -732,7 +729,9 @@ glade_command_delete (GladeWidget *widge
  * from the placeholder).
  */
 void
-glade_command_create (GladeWidgetClass *class, GladePlaceholder *placeholder, GladeProject *project)
+glade_command_create (GladeWidgetClass *class,
+		      GladePlaceholder *placeholder,
+		      GladeProject *project)
 {
 	GladeWidget *widget;
 	GladeWidget *parent = NULL;
@@ -740,8 +739,7 @@ glade_command_create (GladeWidgetClass *
 	g_return_if_fail (GLADE_IS_WIDGET_CLASS (class));
 	g_return_if_fail (placeholder != NULL || GLADE_IS_PROJECT (project));
 
-	if (placeholder)
-	{
+	if (placeholder) {
 		parent = glade_placeholder_get_parent (placeholder);
 		g_return_if_fail (parent != NULL);
 	}
@@ -786,9 +784,36 @@ glade_command_cut_paste_undo (GladeComma
 static gboolean
 glade_command_paste_execute (GladeCommandCutPaste *me)
 {
-	glade_clipboard_paste (me->clipboard, me->placeholder);
+	GladeWidget *widget = me->widget;
+	GladePlaceholder *placeholder = me->placeholder;
+	GladeWidget *parent;
+	GladeProject *project;
+
+	g_return_val_if_fail (g_list_find (me->clipboard->widgets, widget), TRUE);
+
+	parent = glade_placeholder_get_parent (placeholder);
+	project = parent->project;
+
+	widget->name = glade_widget_new_name (project, widget->class);
+	glade_packing_add_properties (widget);
+
+	glade_widget_set_contents (widget);
+	glade_widget_connect_signals (widget);
 
-	me->placeholder = NULL;
+	if (!GLADE_WIDGET_IS_TOPLEVEL (widget)) {
+		gtk_widget_ref (GTK_WIDGET (placeholder));
+
+		glade_placeholder_replace_with_widget (placeholder, widget);
+		glade_widget_set_default_packing_options (widget);
+	}
+
+	glade_project_add_widget (project, widget, parent);
+	glade_project_selection_set (widget, TRUE);
+
+	if (GTK_IS_WIDGET (widget->widget))
+		gtk_widget_show_all (GTK_WIDGET (widget->widget));
+
+	glade_clipboard_remove (me->clipboard, widget);
 
 	return TRUE;
 }
@@ -796,7 +821,22 @@ glade_command_paste_execute (GladeComman
 static gboolean
 glade_command_cut_execute (GladeCommandCutPaste *me)
 {
-	me->placeholder = glade_clipboard_cut (me->clipboard, me->widget);
+	GladeWidget *widget = me->widget;
+
+	g_return_val_if_fail (widget != NULL, TRUE);
+
+	glade_clipboard_add (me->clipboard, widget);
+
+	if (widget->parent != NULL){
+		/* We ref so that the widget and its children are not destroyed. */
+		gtk_widget_ref (GTK_WIDGET (widget->widget));
+
+		me->placeholder = glade_widget_replace_with_placeholder (widget, me->placeholder);
+	}
+
+	gtk_widget_hide (widget->widget);
+
+	glade_project_remove_widget (widget);
 
 	return TRUE;
 }
@@ -810,13 +850,14 @@ glade_command_cut_paste_execute (GladeCo
 {
 	GladeCommandCutPaste *me = (GladeCommandCutPaste *) cmd;
 	gboolean retval;
-	
+
 	if (me->cut)
 		retval = glade_command_cut_execute (me);
 	else
 		retval = glade_command_paste_execute (me);
 
 	me->cut = !me->cut;
+
 	return retval;
 }
 
@@ -825,10 +866,8 @@ glade_command_cut_paste_finalize (GObjec
 {
 	GladeCommandCutPaste *cmd = GLADE_COMMAND_CUT_PASTE (obj);
 
-	/* if a pasted item has been undoed, and now we have to forget about it,
-	 * then we should free the pasted widget (as nobody is going to use it anymore) */
-	if (!cmd->cut)
-		g_object_unref (cmd->widget);
+	g_object_unref (cmd->widget);
+	g_object_unref (cmd->placeholder);
 
 	glade_command_finalize (obj);
 }
@@ -848,26 +887,25 @@ glade_command_cut_paste_collapse (GladeC
 static void
 glade_command_cut_paste_common (GladeWidget *widget,
 				GladePlaceholder *placeholder,
+				GladeProject *project,
 				gboolean cut)
 {
 	GladeCommandCutPaste *me;
 	GladeCommand *cmd;
-	GladeProject *project;
 	GladeProjectWindow *gpw;
 
 	me = (GladeCommandCutPaste *) g_object_new (GLADE_COMMAND_CUT_PASTE_TYPE, NULL);
 	cmd = (GladeCommand *) me;
 	
-	project = glade_project_window_get_project ();
 	gpw = glade_project_window_get ();
 
 	me->cut = cut;
 	me->widget = widget;
 	me->placeholder = placeholder;
 	me->clipboard = gpw->clipboard;
-	
+
 	cmd->description = g_strdup_printf (_("%s %s"), cut ? "Cut" : "Paste", widget->name);
-	
+
 	g_debug(("Pushing: %s\n", cmd->description));
 
 	/*
@@ -878,13 +916,39 @@ glade_command_cut_paste_common (GladeWid
 }
 
 void
-glade_command_paste (GladeWidget *widget, GladePlaceholder *placeholder)
+glade_command_paste (GladePlaceholder *placeholder)
 {
-	glade_command_cut_paste_common (widget, placeholder, FALSE);
+	GladeProjectWindow *gpw;
+	GladeWidget *widget;
+	GladeWidget *parent;
+
+	if (placeholder == NULL) {
+		glade_util_ui_warn (_("Placeholder not selected!"));
+		return;
+	}
+
+	g_return_if_fail (glade_placeholder_is (placeholder));
+	
+	gpw = glade_project_window_get ();
+	widget = gpw->clipboard->curr;
+
+	if (widget == NULL)
+		return;
+
+	parent = glade_placeholder_get_parent (placeholder);
+
+	glade_command_cut_paste_common (widget, placeholder, parent->project, FALSE);
 }
 
 void
 glade_command_cut (GladeWidget *widget)
 {
-	glade_command_cut_paste_common (widget, NULL, TRUE);
+	if (widget == NULL) {
+		glade_util_ui_warn (_("No widget selected!"));
+		return;
+	}
+
+	g_return_if_fail (GLADE_IS_WIDGET (widget));
+
+	glade_command_cut_paste_common (widget, NULL, widget->project, TRUE);
 }
diff -upr gnome2/glade3/src/glade-command.h glade3/src/glade-command.h
--- gnome2/glade3/src/glade-command.h	2003-06-01 11:15:03.000000000 +0200
+++ glade3/src/glade-command.h	2003-06-02 11:11:04.000000000 +0200
@@ -19,7 +19,7 @@ void glade_command_delete (GladeWidget *
 void glade_command_create (GladeWidgetClass *class, GladePlaceholder *placeholder, GladeProject *project);
 
 void glade_command_cut   (GladeWidget *widget);
-void glade_command_paste (GladeWidget *widget, GladePlaceholder *placeholder);
+void glade_command_paste (GladePlaceholder *placeholder);
 
 G_END_DECLS
 

diff -upr gnome2/glade3/src/glade-placeholder.c glade3/src/glade-placeholder.c
--- gnome2/glade3/src/glade-placeholder.c	2003-06-01 11:15:03.000000000 +0200
+++ glade3/src/glade-placeholder.c	2003-06-02 16:17:49.000000000 +0200
@@ -245,8 +245,7 @@ glade_placeholder_on_button_press_event 
 					 gpointer not_used)
 {
 	GladeProjectWindow *gpw = glade_project_window_get ();
-	GladeProject *project = glade_project_window_get_project (gpw);
-	
+
 	if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
 
 		if (gpw->add_class != NULL) {
@@ -369,8 +368,7 @@ glade_placeholder_new ()
 
 #undef GLADE_PLACEHOLDER_SIZE
 
-void glade_placeholder_add (GladeWidgetClass *class,
-			    GladeWidget *widget)
+void glade_placeholder_add (GladeWidgetClass *class, GladeWidget *widget)
 {
 
 	if (GLADE_WIDGET_CLASS_TOPLEVEL (class)) {
@@ -389,10 +387,11 @@ void glade_placeholder_add (GladeWidgetC
 
 }
 
-
 GladeWidget *
 glade_placeholder_get_parent (GladePlaceholder *placeholder)
 {
+	g_return_val_if_fail (glade_placeholder_is (placeholder), NULL);
+
 	GladeWidget *parent = NULL;
 	GtkWidget *widget = gtk_widget_get_parent (placeholder);
 
@@ -409,75 +408,26 @@ glade_placeholder_get_parent (GladePlace
 }
 
 void
-glade_placeholder_replace (GladePlaceholder *placeholder, GladeWidget *parent, GladeWidget *child)
+glade_placeholder_replace_with_widget (GladePlaceholder *placeholder,
+			   	       GladeWidget *widget)
 {
-	g_return_if_fail (GTK_IS_WIDGET (placeholder));
-	
+	GladeWidget *parent;
+
+	g_return_if_fail (glade_placeholder_is (placeholder));
+	g_return_if_fail (GLADE_IS_WIDGET (widget));
+
+	parent = glade_placeholder_get_parent (placeholder);
+
 	if (parent->class->placeholder_replace != NULL)
-		parent->class->placeholder_replace (GTK_WIDGET (placeholder), child->widget, parent->widget);
+		parent->class->placeholder_replace (GTK_WIDGET (placeholder),
+						    widget->widget,
+						    parent->widget);
 	else
 		g_warning ("Could not replace a placeholder because a replace "
 			   " function has not been implemented for \"%s\"\n",
 			   parent->class->name);
 }
 
-
-
-GladePlaceholder *
-glade_placeholder_get_from_properties (GladeWidget *parent,
-				       GHashTable *properties)
-{
-	GladePlaceholder *placeholder = NULL;
-	GList *list;
-
-	if (glade_widget_class_is (parent->class, "GtkVBox") ||
-	    glade_widget_class_is (parent->class, "GtkHBox")) {
-		GtkBoxChild *box_child;
-		const gchar *val;
-		
-		list = gtk_container_children (GTK_CONTAINER (parent->widget));
-		val = g_hash_table_lookup (properties, "position");
-		if (!val)
-			return NULL;
-
-		box_child = (GtkBoxChild *) g_list_nth (list, atoi (val));
-		placeholder = box_child->widget;
-		g_assert (placeholder);
-	} else if (glade_widget_class_is (parent->class, "GtkTable")) {
-		GtkTableChild *child;
-		const char *val;
-		int col;
-		int row;
-
-		val = g_hash_table_lookup (properties, "cell_x");
-		if (!val)
-			return NULL;
-
-		col = atoi (val);
-		val = g_hash_table_lookup (properties, "cell_y");
-		if (!val)
-			return NULL;
-
-		row = atoi (val);
-
-		list = GTK_TABLE (parent->widget)->children;
-		for (; list; list = list->next) {
-			child = list->data;
-			if ((child->left_attach == col) &&
-			    (child->top_attach  == row)) {
-				placeholder = child->widget;
-				break;
-			}
-		}
-	} else if (glade_widget_class_is (parent->class, "GtkWindow")) {
-		placeholder = GTK_BIN (parent->widget)->child;
-	} else {
-		glade_implement_me ();
-	}
-
-	return placeholder;
-}
-
 gboolean
 glade_placeholder_is (GtkWidget *widget)
 {
@@ -493,117 +443,3 @@ glade_placeholder_is (GtkWidget *widget)
 	return is;
 }
 
-
-void
-glade_placeholder_remove_all (GtkWidget *widget)
-{
-	GladeWidget *gwidget, *child_widget;
-	
-	
-	gwidget = glade_widget_get_from_gtk_widget (widget);
-	g_return_if_fail (widget != NULL);
-	
-	if (glade_widget_class_is (gwidget->class, "GtkVBox") ||
-	    glade_widget_class_is (gwidget->class, "GtkHBox")) {
-		GList *element;
-		GtkBox *box;
-		GtkBoxChild *box_child;
-
-		box = GTK_BOX (widget);
-		
-		element = g_list_first (box->children);
-		while (element != NULL) {
-			box_child = element->data;
-			if (glade_placeholder_is (box_child->widget)) {
-				child_widget = glade_widget_get_from_gtk_widget (box_child->widget);
-				if (child_widget)
-					glade_command_delete (child_widget);
-				gtk_container_remove (GTK_CONTAINER (box),
-						      box_child->widget);
-				element = g_list_first (box->children);
-			} else {
-				element = g_list_next (element);
-			}		
-		}
-	} else if (glade_widget_class_is (gwidget->class, "GtkDialog")) {
-		GList *element;
-		GtkBox *box;
-		GtkBoxChild *box_child;
-		gint i;
-
-		box = GTK_BOX (GTK_DIALOG (widget)->vbox);
-		for (i = 0; i < 2; i++) {
-			
-			element = g_list_first (box->children);
-			
-			while (element != NULL) {
-				box_child = element->data;
-				if (glade_placeholder_is (box_child->widget)) {
-					child_widget = glade_widget_get_from_gtk_widget (box_child->widget);
-					if (child_widget)
-						glade_command_delete (child_widget);
-					gtk_container_remove (GTK_CONTAINER (box),
-					box_child->widget);
-					element = g_list_first (box->children);
-				} else {
-					element = g_list_next (element);
-				}
-			}
-			box = GTK_BOX (GTK_DIALOG (widget)->action_area);
-		}
-	} else if (glade_widget_class_is (gwidget->class, "GtkTable")) {
-		GList *element;
-		GtkTableChild *table_child;
-
-		element = g_list_first (GTK_TABLE (widget)->children);
-		while (element != NULL) {
-			table_child = element->data;
-			if (glade_placeholder_is (table_child->widget)) {
-				child_widget = glade_widget_get_from_gtk_widget (table_child->widget);
-				if (child_widget)
-					glade_command_delete (child_widget);
-				gtk_container_remove (GTK_CONTAINER (widget),
-						      table_child->widget);
-				element = g_list_first (GTK_TABLE (widget)->children);
-			} else {
-				element = g_list_next (element);
-			}
-		}
-	} else {
-		glade_implement_me ();
-	}
-
-}
-
-void
-glade_placeholder_fill_empty (GtkWidget *widget)
-{
-	GList *children;
-	gboolean empty = TRUE;
-
-	if (!GTK_IS_CONTAINER (widget))
-		return;
-	
-	/* fill with placeholders the containers that are inside of this container */
-	children = gtk_container_get_children (GTK_CONTAINER (widget));
-
-	/* loop over the children of this container, and fill them with placeholders */
-	while (children != NULL) {
-		glade_placeholder_fill_empty (GTK_WIDGET (children->data));
-		children = children->next;
-		empty = FALSE;
-	}
-
-	if (empty) {
-		/* retrieve the desired number of placeholders that this widget should hold */
-		int nb_children = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "glade_nb_placeholders"));
-		int i;
-
-		if (nb_children == 0 && GTK_IS_BIN (widget))
-			nb_children = 1;
-
-		for (i = nb_children; i > 0; i--)
-			gtk_container_add (GTK_CONTAINER (widget), glade_placeholder_new ());
-	}
-}
-
diff -upr gnome2/glade3/src/glade-placeholder.h glade3/src/glade-placeholder.h
--- gnome2/glade3/src/glade-placeholder.h	2003-05-24 17:41:46.000000000 +0200
+++ glade3/src/glade-placeholder.h	2003-06-02 16:10:38.000000000 +0200
@@ -17,9 +17,8 @@ GladeWidget * glade_placeholder_get_pare
 
 void glade_placeholder_add_methods_to_class (GladeWidgetClass *class);
 
-void glade_placeholder_replace (GladePlaceholder *placeholder,
-				GladeWidget *parent,
-				GladeWidget *child);
+void glade_placeholder_replace_with_widget (GladePlaceholder *placeholder,
+					    GladeWidget *widget);
 
 GladePlaceholder * glade_placeholder_get_from_properties (GladeWidget *parent,
 							  GHashTable *properties);
@@ -30,7 +29,6 @@ gboolean glade_placeholder_is (GtkWidget
 
 void glade_placeholder_remove_all (GtkWidget *widget);
 
-void glade_placeholder_fill_empty (GtkWidget *widget);
 
 G_END_DECLS
 
diff -upr gnome2/glade3/src/glade-popup.c glade3/src/glade-popup.c
--- gnome2/glade3/src/glade-popup.c	2003-05-24 17:41:46.000000000 +0200
+++ glade3/src/glade-popup.c	2003-06-02 15:41:41.000000000 +0200
@@ -47,7 +47,7 @@ glade_popup_copy_cb (GtkMenuItem *item, 
 	GladeProjectWindow *gpw;
 
 	gpw = glade_project_window_get ();
-	glade_clipboard_copy (gpw->clipboard, widget);
+	glade_clipboard_add_copy (gpw->clipboard, widget);
 }
 
 static void
@@ -70,10 +70,7 @@ static void
 glade_popup_placeholder_paste_cb (GtkMenuItem *item,
 				  GladePlaceholder *placeholder)
 {
-	GladeProjectWindow *gpw = glade_project_window_get ();
-
-	if (gpw->clipboard->curr)
-		glade_command_paste (gpw->clipboard->curr, placeholder);
+	glade_command_paste (placeholder);
 }
 
 static void
diff -upr gnome2/glade3/src/glade-project.c glade3/src/glade-project.c
--- gnome2/glade3/src/glade-project.c	2003-05-24 17:41:46.000000000 +0200
+++ glade3/src/glade-project.c	2003-06-02 16:24:36.000000000 +0200
@@ -154,35 +154,50 @@ static void
 glade_project_add_widget_real (GladeProject *project,
 			       GladeWidget *widget)
 {
-	GladeWidget *child;
-	GList *list;
-
 	widget->project = project;
 
-	/*
-	 * Add all the children as well.
-	 */
-	list = widget->children;
-	for (; list; list = list->next) {
-		child = list->data;
-		glade_project_add_widget_real (project, child);
-		child->project = project;
-	}
-	
 	project->widgets = g_list_prepend (project->widgets, widget);
 
 	gtk_signal_emit (GTK_OBJECT (project),
 			 glade_project_signals [ADD_WIDGET], widget);
 }
 
+/**
+ * glade_project_add_widget:
+ * @project: the project the widget is added to
+ * @widget: the GladeWidget to add
+ * @parent: the GladeWidget @widget is reparented to
+ *
+ * Adds a widget to the project. Parent should be NULL for toplevels.
+ **/
 void
 glade_project_add_widget (GladeProject *project,
-			  GladeWidget  *widget)
+			  GladeWidget *widget,
+			  GladeWidget *parent)
 {
+	GladeWidget *child;
+	GList *list;
+
 	g_return_if_fail (GLADE_IS_PROJECT (project));
-	g_return_if_fail (GTK_IS_OBJECT (project));
+	g_return_if_fail (GLADE_IS_WIDGET (widget));
 
 	glade_project_add_widget_real (project, widget);
+	widget->parent = parent;
+
+	/* Add all the children as well */
+	for (list = widget->children; list; list = list->next) {
+		child = list->data;
+		glade_project_add_widget_real (project, child);
+	}
+
+	/* reparent */
+	if (parent) {
+		g_return_if_fail (GLADE_IS_WIDGET (parent));
+
+		widget->parent = parent;
+		parent->children = g_list_prepend (parent->children, widget);
+	}
+
 	project->changed = TRUE;
 }
 
@@ -207,8 +222,9 @@ glade_project_remove_widget_real (GladeP
 	}
 	
 	project->selection = g_list_remove (project->selection, widget);
-	project->widgets   = g_list_remove (project->widgets, widget);
+	glade_project_selection_changed (project);
 
+	project->widgets   = g_list_remove (project->widgets, widget);
 	gtk_signal_emit (GTK_OBJECT (project),
 			 glade_project_signals [REMOVE_WIDGET], widget);
 }
@@ -223,7 +239,7 @@ glade_project_remove_widget (GladeWidget
 	project = widget->project;
 
 	glade_project_remove_widget_real (project, widget);
-	glade_project_selection_changed (project);
+
 	project->changed = TRUE;
 }
 	
diff -upr gnome2/glade3/src/glade-project.h glade3/src/glade-project.h
--- gnome2/glade3/src/glade-project.h	2003-05-24 17:41:46.000000000 +0200
+++ glade3/src/glade-project.h	2003-06-01 21:25:47.000000000 +0200
@@ -67,7 +67,8 @@ gboolean glade_project_save (GladeProjec
 /* Widget related stuff */
 void glade_project_remove_widget (GladeWidget *widget);
 void glade_project_add_widget (GladeProject  *project,
-			       GladeWidget *glade_widget);
+			       GladeWidget *widget,
+			       GladeWidget *parent);
 
 GladeWidget *glade_project_get_widget_by_name (GladeProject *project, const char *name);
 char *glade_project_new_widget_name (GladeProject *project, const char *base_name);
diff -upr gnome2/glade3/src/glade-project-window.c glade3/src/glade-project-window.c
--- gnome2/glade3/src/glade-project-window.c	2003-06-01 11:15:03.000000000 +0200
+++ glade3/src/glade-project-window.c	2003-06-02 14:28:19.000000000 +0200
@@ -349,7 +349,7 @@ gpw_copy_cb (void)
 	widget = gpw->active_widget;
 
 	if (widget)
-		glade_clipboard_copy (gpw->clipboard, widget);
+		glade_clipboard_add_copy (gpw->clipboard, widget);
 }
 
 static void
@@ -371,7 +371,8 @@ gpw_paste_cb (void)
 	GladeProjectWindow *gpw;
 
 	gpw = glade_project_window_get ();
-	glade_command_paste (gpw->active_widget, gpw->active_placeholder);
+	
+	glade_command_paste (gpw->active_placeholder);
 }
 
 static void
diff -upr gnome2/glade3/src/glade-widget.c glade3/src/glade-widget.c
--- gnome2/glade3/src/glade-widget.c	2003-06-01 11:15:04.000000000 +0200
+++ glade3/src/glade-widget.c	2003-06-02 16:48:47.000000000 +0200
@@ -802,19 +802,45 @@ glade_widget_new_full (GladeWidgetClass 
 
 	glade_packing_add_properties (widget);
 	glade_widget_create_gtk_widget (widget);
-	/*
-	glade_project_add_widget (project, widget);
 
-	if (parent)
-		parent->children = g_list_prepend (parent->children, widget);
-	*/
-	
 	glade_widget_set_contents (widget);
 	glade_widget_connect_signals (widget);
 
 	return widget;
 }
 
+static void
+glade_widget_fill_empty (GtkWidget *widget)
+{
+	GList *children;
+	gboolean empty = TRUE;
+
+	if (!GTK_IS_CONTAINER (widget))
+		return;
+	
+	/* fill with placeholders the containers that are inside of this container */
+	children = gtk_container_get_children (GTK_CONTAINER (widget));
+
+	/* loop over the children of this container, and fill them with placeholders */
+	while (children != NULL) {
+		glade_widget_fill_empty (GTK_WIDGET (children->data));
+		children = children->next;
+		empty = FALSE;
+	}
+
+	if (empty) {
+		/* retrieve the desired number of placeholders that this widget should hold */
+		int nb_children = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "glade_nb_placeholders"));
+		int i;
+
+		if (nb_children == 0 && GTK_IS_BIN (widget))
+			nb_children = 1;
+
+		for (i = nb_children; i > 0; i--)
+			gtk_container_add (GTK_CONTAINER (widget), glade_placeholder_new ());
+	}
+}
+
 static GtkWidget *
 glade_widget_append_query (GtkWidget *table,
 			   GladePropertyClass *property_class,
@@ -1004,7 +1030,7 @@ glade_widget_new_from_class (GladeWidget
 
 	/* If we are a container, add the placeholders */
 	if (g_type_is_a (class->type,  GTK_TYPE_CONTAINER))
-		glade_placeholder_fill_empty (widget->widget);
+		glade_widget_fill_empty (widget->widget);
 	
 	if (result) 
 		glade_property_query_result_destroy (result);
@@ -1197,19 +1223,30 @@ glade_widget_clone (GladeWidget *widget)
 	return clone;
 }
 
+/**
+ * glade_widget_replace_with_placeholder:
+ * @widget:
+ * @placeholder:
+ *
+ * Replaces @widget with @placeholder. If @placeholder is NULL a new one is created.
+ **/
 GladePlaceholder *
-glade_widget_replace_with_placeholder (GladeWidget *widget)
+glade_widget_replace_with_placeholder (GladeWidget *widget, GladePlaceholder *placeholder)
 {
-	GladePlaceholder *placeholder;
-	GladeWidget *parent = widget->parent;
+	g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL);
+
+	if (placeholder == NULL)
+		placeholder = glade_placeholder_new (widget->parent);
+	else
+		g_return_val_if_fail (glade_placeholder_is (placeholder), NULL);
 
-	/* Replace the slot it was occuping with a placeholder */
-	placeholder = glade_placeholder_new (widget->parent);
 	if (widget->parent->class->placeholder_replace)
-		widget->parent->class->placeholder_replace (widget->widget, GTK_WIDGET (placeholder), widget->parent->widget);
+		widget->parent->class->placeholder_replace (widget->widget,
+							    GTK_WIDGET (placeholder),
+							    widget->parent->widget);
 
 	/* Remove it from the parent's child list */
-	parent->children = g_list_remove (parent->children, widget);
+	widget->parent->children = g_list_remove (widget->parent->children, widget);
 
 	/* Return the placeholder, if some one needs it, he can use it. */
 	return placeholder;
@@ -1444,7 +1481,9 @@ glade_widget_apply_properties_from_hash 
 }
 
 static gboolean
-glade_widget_new_child_from_node (GladeXmlNode *node, GladeProject *project, GladeWidget *parent)
+glade_widget_new_child_from_node (GladeXmlNode *node,
+				  GladeProject *project,
+				  GladeWidget *parent)
 {
 	GladeXmlNode *child_node;
 	GladeXmlNode *child_properties;
@@ -1529,7 +1568,7 @@ glade_widget_new_child_from_node (GladeX
 		g_value_unset (&string_value);
 	}
 	
-	glade_placeholder_fill_empty (parent->widget);
+	glade_widget_fill_empty (parent->widget);
 
 	return TRUE;
 }
diff -upr gnome2/glade3/src/glade-widget.h glade3/src/glade-widget.h
--- gnome2/glade3/src/glade-widget.h	2003-06-01 11:15:04.000000000 +0200
+++ glade3/src/glade-widget.h	2003-06-02 14:16:06.000000000 +0200
@@ -90,8 +90,9 @@ void glade_widget_flag_unselected (Glade
 void glade_widget_select (GladeWidget *widget);
 
 GladeWidget *glade_widget_clone (GladeWidget *widget);
-GladePlaceholder * glade_widget_replace_with_placeholder (GladeWidget *widget);
-GladeWidget * glade_widget_get_from_gtk_widget (GtkWidget *widget);
+GladePlaceholder *glade_widget_replace_with_placeholder (GladeWidget *widget,
+							 GladePlaceholder *placeholder);
+GladeWidget *glade_widget_get_from_gtk_widget (GtkWidget *widget);
 
 /* Xml saving & reading */
 GladeXmlNode * glade_widget_write (GladeXmlContext *context, GladeWidget *widget);

Reply via email to