From 81caf21c40a6dd38caf4b64d7b9941151c20c6d8 Mon Sep 17 00:00:00 2001
From: Ivica Ico Bukvic <ico@vt.edu>
Date: Thu, 15 Dec 2011 17:58:15 -0500
Subject: [PATCH] finished undo implementation, added consistency to how canvas
 properties window is handled in undo situations, removed debug output.

---
 src/g_canvas.c |  6 ++--
 src/g_editor.c | 78 ++++++++++++++++++++++++++++++--------------------
 src/g_undo.c   | 18 ++++++++----
 src/g_undo.h   | 10 +++++++
 src/pd.tk      | 22 ++++++++++++++
 5 files changed, 96 insertions(+), 38 deletions(-)

diff --git a/src/g_canvas.c b/src/g_canvas.c
index aa06ac10c..3384ece3e 100644
--- a/src/g_canvas.c
+++ b/src/g_canvas.c
@@ -1799,7 +1799,8 @@ void canvasgop__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx, t_flo
 		if(sh->h_scale)														//enter if resize_gop hook
 		{
 			/* first set up the undo apply */
-			canvas_canvas_setundo(x);
+			//canvas_canvas_setundo(x);
+			canvas_undo_add(x, 8, "apply", canvas_undo_set_canvas(x));
 
 			if (sh->h_dragx || sh->h_dragy) 
 			{
@@ -1858,7 +1859,8 @@ void canvasgop__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx, t_flo
 		else 																//enter if move_gop hook
 		{
 			/* first set up the undo apply */
-			canvas_canvas_setundo(x);
+			//canvas_canvas_setundo(x);
+			canvas_undo_add(x, 8, "apply", canvas_undo_set_canvas(x));
 
 			if (sh->h_dragx || sh->h_dragy) 
 			{
diff --git a/src/g_editor.c b/src/g_editor.c
index baa942198..1da6418e4 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -1163,7 +1163,7 @@ typedef struct _undo_arrange
 	int u_newindex;				/* new index */
 } t_undo_arrange;
 
-static void *canvas_undo_set_arrange(t_canvas *x, t_gobj *obj, int newindex)
+void *canvas_undo_set_arrange(t_canvas *x, t_gobj *obj, int newindex)
 {
 	// newindex tells us is the new index at the beginning (0) or the end (1)
 
@@ -1191,7 +1191,7 @@ static void *canvas_undo_set_arrange(t_canvas *x, t_gobj *obj, int newindex)
     return (buf);
 }
 
-static void canvas_undo_arrange(t_canvas *x, void *z, int action)
+void canvas_undo_arrange(t_canvas *x, void *z, int action)
 {
     t_undo_arrange *buf = z;
 	t_gobj *y=NULL, *prev=NULL, *next=NULL;
@@ -1323,38 +1323,40 @@ typedef struct _undo_canvas_properties
     unsigned int gl_hidetext:1;     /* hide object-name + args when doing graph on parent */
 } t_undo_canvas_properties;
 
-t_undo_canvas_properties global_buf;
+//t_undo_canvas_properties global_buf;
 
-static void *canvas_undo_set_canvas(t_canvas *x)
+void *canvas_undo_set_canvas(t_canvas *x)
 {
 	/* enable editor (in case it is disabled) */
 	//if (x->gl_havewindow && !x->gl_edit)
 	//	canvas_editmode(x, 1);
 
-	global_buf.gl_pixwidth = x->gl_pixwidth;
-	global_buf.gl_pixheight = x->gl_pixheight;
-	global_buf.gl_x1 = x->gl_x1;
-	global_buf.gl_y1 = x->gl_y1;
-	global_buf.gl_x2 = x->gl_x2;
-	global_buf.gl_y2 = x->gl_y2;
-	global_buf.gl_screenx1 = x->gl_screenx1;
-	global_buf.gl_screeny1 = x->gl_screeny1;
-	global_buf.gl_screenx2 = x->gl_screenx2;
-	global_buf.gl_screeny2 = x->gl_screeny2;
-	global_buf.gl_xmargin = x->gl_xmargin;
-	global_buf.gl_ymargin = x->gl_ymargin;
-	global_buf.gl_goprect = x->gl_goprect;
-	global_buf.gl_isgraph = x->gl_isgraph;
-	global_buf.gl_hidetext = x->gl_hidetext;
+	t_undo_canvas_properties *buf = (t_undo_canvas_properties *)getbytes(sizeof(*buf));
+
+	buf->gl_pixwidth = x->gl_pixwidth;
+	buf->gl_pixheight = x->gl_pixheight;
+	buf->gl_x1 = x->gl_x1;
+	buf->gl_y1 = x->gl_y1;
+	buf->gl_x2 = x->gl_x2;
+	buf->gl_y2 = x->gl_y2;
+	buf->gl_screenx1 = x->gl_screenx1;
+	buf->gl_screeny1 = x->gl_screeny1;
+	buf->gl_screenx2 = x->gl_screenx2;
+	buf->gl_screeny2 = x->gl_screeny2;
+	buf->gl_xmargin = x->gl_xmargin;
+	buf->gl_ymargin = x->gl_ymargin;
+	buf->gl_goprect = x->gl_goprect;
+	buf->gl_isgraph = x->gl_isgraph;
+	buf->gl_hidetext = x->gl_hidetext;
 	
-    return (&global_buf);
+    return (buf);
 }
 
 extern int gfxstub_haveproperties(void *key);
 
-static void canvas_undo_canvas_apply(t_canvas *x, void *z, int action)
+void canvas_undo_canvas_apply(t_canvas *x, void *z, int action)
 {
-    t_undo_canvas_properties *buf = z;
+    t_undo_canvas_properties *buf = (t_undo_canvas_properties *)z;
     t_undo_canvas_properties tmp;
 
 	if (!x->gl_edit)
@@ -1362,11 +1364,11 @@ static void canvas_undo_canvas_apply(t_canvas *x, void *z, int action)
 
 	if (action == UNDO_UNDO || action == UNDO_REDO)
 	{
-		/*//close properties window first
+		//close properties window first
 		t_int properties = gfxstub_haveproperties((void *)x);
 		if (properties) {
 			sys_vgui("destroy .gfxstub%lx\n", properties);
-		}*/
+		}
 
 		//store current canvas values into temporary data holder
 		tmp.gl_pixwidth = x->gl_pixwidth;
@@ -1442,8 +1444,17 @@ static void canvas_undo_canvas_apply(t_canvas *x, void *z, int action)
 		}
 
 		//if properties window is open, update the properties with the previous window properties		
-		t_int properties = gfxstub_haveproperties((void *)x);
+		/*t_int properties = gfxstub_haveproperties((void *)x);
 		if (properties) {
+			sys_vgui("pdtk_canvas_dialog_undo_update .gfxstub%lx %d %d\n", properties, x->gl_isgraph, x->gl_hidetext);
+			sys_vgui(".gfxstub%lx.xscale.entry delete 0 end\n", properties);
+			sys_vgui(".gfxstub%lx.xrange.entry1 insert 0 %d\n", properties, x->gl_x1);
+			sys_vgui(".gfxstub%lx.yrange.entry1 delete 0 end\n", properties);
+			sys_vgui(".gfxstub%lx.yrange.entry1 insert 0 %d\n", properties, x->gl_y1);
+			sys_vgui(".gfxstub%lx.xrange.entry2 delete 0 end\n", properties);
+			sys_vgui(".gfxstub%lx.xrange.entry2 insert 0 %d\n", properties, x->gl_x2);
+			sys_vgui(".gfxstub%lx.yrange.entry2 delete 0 end\n", properties);
+			sys_vgui(".gfxstub%lx.yrange.entry2 insert 0 %d\n", properties, x->gl_y2);
 			sys_vgui(".gfxstub%lx.xrange.entry3 delete 0 end\n", properties);
 			sys_vgui(".gfxstub%lx.xrange.entry3 insert 0 %d\n", properties, x->gl_pixwidth);
 			sys_vgui(".gfxstub%lx.yrange.entry3 delete 0 end\n", properties);
@@ -1452,15 +1463,17 @@ static void canvas_undo_canvas_apply(t_canvas *x, void *z, int action)
 			sys_vgui(".gfxstub%lx.xrange.entry4 insert 0 %d\n", properties, x->gl_xmargin);
 			sys_vgui(".gfxstub%lx.yrange.entry4 delete 0 end\n", properties);
 			sys_vgui(".gfxstub%lx.yrange.entry4 insert 0 %d\n", properties, x->gl_ymargin);
-		}
+		}*/
 
 		sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)x);
-		sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)canvas);
+		if (canvas != x)
+			sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)canvas);
 	}
 
     else if (action == UNDO_FREE)
     {
-		//do nothing since undo apply uses a global_buf struct rather than a pointer
+		if (buf)
+			t_freebytes(buf, sizeof(*buf));
     }
 }
 
@@ -2094,7 +2107,8 @@ static void canvas_donecanvasdialog(t_glist *x,
 			graphme!=(x->gl_isgraph+2*x->gl_hidetext) || x->gl_pixwidth!=xpix ||
 			x->gl_pixheight!=ypix || x->gl_xmargin!=xmargin || x->gl_ymargin!=ymargin) {*/
 	{	
-		canvas_canvas_setundo(x);
+		//canvas_canvas_setundo(x);
+		canvas_undo_add(x, 8, "apply", canvas_undo_set_canvas(x));
 		//fprintf(stderr,"canvas_apply_undo\n");
 	}
 
@@ -2338,14 +2352,16 @@ static void canvas_done_popup(t_canvas *x, t_float which, t_float xpos, t_float
 	if (which == 3 && y_end != oldy) /* to front */
 	{
 		/* create appropriate undo action */
-		canvas_arrange_setundo(x, oldy, 1);
+		//canvas_arrange_setundo(x, oldy, 1);
+		canvas_undo_add(x, 7, "arrange", canvas_undo_set_arrange(x, oldy, 1));
 
 		canvas_doarrange(x, which, oldy, oldy_prev, oldy_next);
 	}
 	if (which == 4 && y_begin != oldy) /* to back */
 	{
 		/* create appropriate undo action */
-		canvas_arrange_setundo(x, oldy, 0);
+		//canvas_arrange_setundo(x, oldy, 0);
+		canvas_undo_add(x, 7, "arrange", canvas_undo_set_arrange(x, oldy, 0));
 
 		canvas_doarrange(x, which, oldy, oldy_prev, oldy_next);
 	}
diff --git a/src/g_undo.c b/src/g_undo.c
index c9dd628df..22f106774 100644
--- a/src/g_undo.c
+++ b/src/g_undo.c
@@ -39,7 +39,7 @@ t_undo_action *canvas_undo_init(t_canvas *x)
 
 t_undo_action *canvas_undo_add(t_canvas *x, int type, const char *name, void *data)
 {
-	fprintf(stderr,"canvas_undo_add %d\n", type);
+	//fprintf(stderr,"canvas_undo_add %d\n", type);
 	t_undo_action *a = canvas_undo_init(x);
 	a->type = type;
 	a->data = (void *)data;
@@ -53,7 +53,7 @@ void canvas_undo_undo(t_canvas *x)
 {
 	if (x->u_queue && x->u_last != x->u_queue) {
 		we_are_undoing = 1;
-		fprintf(stderr,"canvas_undo_undo %d\n", x->u_last->type);
+		//fprintf(stderr,"canvas_undo_undo %d\n", x->u_last->type);
 		glist_noselect(x);
         switch(x->u_last->type)
         {
@@ -63,6 +63,8 @@ void canvas_undo_undo(t_canvas *x)
 		    case 4:	canvas_undo_move(x, x->u_last->data, UNDO_UNDO); break;			//move
 		    case 5:	canvas_undo_paste(x, x->u_last->data, UNDO_UNDO); break;		//paste
 		    case 6:	canvas_undo_apply(x, x->u_last->data, UNDO_UNDO); break;		//apply
+		    case 7:	canvas_undo_arrange(x, x->u_last->data, UNDO_UNDO); break;		//arrange
+		    case 8:	canvas_undo_canvas_apply(x, x->u_last->data, UNDO_UNDO); break;	//canvas apply
 		    case 9:	canvas_undo_create(x, x->u_last->data, UNDO_UNDO); break;		//create
 		    case 10:canvas_undo_recreate(x, x->u_last->data, UNDO_UNDO); break;		//recreate
 		    default:
@@ -84,7 +86,7 @@ void canvas_undo_redo(t_canvas *x)
 	if (x->u_queue && x->u_last->next) {
 		we_are_undoing = 1;
 		x->u_last = x->u_last->next;
-		fprintf(stderr,"canvas_undo_redo %d\n", x->u_last->type);
+		//fprintf(stderr,"canvas_undo_redo %d\n", x->u_last->type);
 		glist_noselect(x);
         switch(x->u_last->type)
         {
@@ -94,6 +96,8 @@ void canvas_undo_redo(t_canvas *x)
 		    case 4:	canvas_undo_move(x, x->u_last->data, UNDO_REDO); break;			//move
 		    case 5:	canvas_undo_paste(x, x->u_last->data, UNDO_REDO); break;		//paste
 		    case 6:	canvas_undo_apply(x, x->u_last->data, UNDO_REDO); break;		//apply
+		    case 7:	canvas_undo_arrange(x, x->u_last->data, UNDO_REDO); break;		//arrange
+		    case 8:	canvas_undo_canvas_apply(x, x->u_last->data, UNDO_REDO); break;	//canvas apply
 		    case 9:	canvas_undo_create(x, x->u_last->data, UNDO_REDO); break;		//create
 		    case 10:canvas_undo_recreate(x, x->u_last->data, UNDO_REDO); break;		//recreate
 		    default:
@@ -111,7 +115,7 @@ void canvas_undo_redo(t_canvas *x)
 
 void canvas_undo_rebranch(t_canvas *x)
 {
-	fprintf(stderr,"canvas_undo_rebranch");
+	//fprintf(stderr,"canvas_undo_rebranch");
 	if (x->u_last->next) {
 		t_undo_action *a;
 		for(a = x->u_last->next; a; a = a->next) {
@@ -124,6 +128,8 @@ void canvas_undo_rebranch(t_canvas *x)
 				case 4:	canvas_undo_move(x, a->data, UNDO_FREE); break;			//move
 				case 5:	canvas_undo_paste(x, a->data, UNDO_FREE); break;		//paste
 				case 6:	canvas_undo_apply(x, a->data, UNDO_FREE); break;		//apply
+		    	case 7:	canvas_undo_arrange(x, a->data, UNDO_FREE); break;		//arrange
+			    case 8:	canvas_undo_canvas_apply(x, a->data, UNDO_FREE); break;	//canvas apply
 				case 9:	canvas_undo_create(x, a->data, UNDO_FREE); break;		//create
 				case 10:canvas_undo_recreate(x, a->data, UNDO_FREE); break;		//recreate
 				default:
@@ -132,7 +138,7 @@ void canvas_undo_rebranch(t_canvas *x)
 			freebytes(a, sizeof(*a));
 		}
 	}
-	fprintf(stderr,"done!\n");
+	//fprintf(stderr,"done!\n");
 }
 
 void canvas_undo_check_canvas_pointers(t_canvas *x)
@@ -161,6 +167,8 @@ void canvas_undo_free(t_canvas *x)
 				case 4:	canvas_undo_move(x, a->data, UNDO_FREE); break;			//move
 				case 5:	canvas_undo_paste(x, a->data, UNDO_FREE); break;		//paste
 				case 6:	canvas_undo_paste(x, a->data, UNDO_FREE); break;		//apply
+		    	case 7:	canvas_undo_arrange(x, a->data, UNDO_FREE); break;		//arrange
+			    case 8:	canvas_undo_canvas_apply(x, a->data, UNDO_FREE); break;	//canvas apply
 				case 9:	canvas_undo_create(x, a->data, UNDO_FREE); break;		//create
 				case 10:canvas_undo_recreate(x, a->data, UNDO_FREE); break;		//recreate
 				default:
diff --git a/src/g_undo.h b/src/g_undo.h
index 61c2c96ef..7614758de 100644
--- a/src/g_undo.h
+++ b/src/g_undo.h
@@ -95,6 +95,16 @@ EXTERN void canvas_undo_paste(t_canvas *x, void *z, int action);
 EXTERN void *canvas_undo_set_apply(t_canvas *x, int n);
 EXTERN void canvas_undo_apply(t_canvas *x, void *z, int action);
 
+/* --------- 7. arrange ---------- */
+
+EXTERN void *canvas_undo_set_arrange(t_canvas *x, t_gobj *obj, int newindex);
+EXTERN void canvas_undo_arrange(t_canvas *x, void *z, int action);
+
+/* --------- 8. canvas apply ----- */
+
+EXTERN void *canvas_undo_set_canvas(t_canvas *x);
+EXTERN void canvas_undo_canvas_apply(t_canvas *x, void *z, int action);
+
 /* --------- 9. create ----------- */
 
 EXTERN void canvas_undo_create(t_canvas *x, void *z, int action);
diff --git a/src/pd.tk b/src/pd.tk
index d8d15b574..506e18381 100644
--- a/src/pd.tk
+++ b/src/pd.tk
@@ -4830,6 +4830,28 @@ proc canvas_checkcommand {id} {
     }
 }
 
+proc pdtk_canvas_dialog_undo_update {name x y} {
+	if {$x==0} {
+		$name.graphme instate {selected} {
+			$name.graphme invoke
+		}
+	} elseif {$x==1} {
+		$name.graphme instate {!selected} {
+			$name.graphme invoke
+		}
+	}
+
+	if {$y==0} {
+		$name.hidetext instate {selected} {
+			$name.hidetext invoke
+		}
+	} elseif {$y==1} {
+		$name.hidetext instate {!selected} {
+			$name.hidetext invoke
+		}
+	}
+}
+
 proc pdtk_canvas_dialog {id xscale yscale graphme x1 y1 x2 y2 \
                              xpix ypix xmargin ymargin} {
     set vid [string trimleft $id .]
-- 
GitLab