changeset 194:45d9a1e2764d

Add mb_subtree_free animate action and fix bugs. - Free members of a coord in rdman_coord_subtree_free(). - Fix core dump issue of subject_notify() that can not free subjects well.
author Thinker K.F. Li <thinker@branda.to>
date Wed, 19 Nov 2008 20:53:40 +0800
parents 923d91dfb6af
children 5235aded379c
files examples/tank/tank_main.c include/mb_animate.h src/Makefile.am src/animate.c src/observer.c src/redraw_man.c src/shift.c src/subtree_free.c
diffstat 8 files changed, 97 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/examples/tank/tank_main.c	Wed Nov 19 11:26:01 2008 +0800
+++ b/examples/tank/tank_main.c	Wed Nov 19 20:53:40 2008 +0800
@@ -396,6 +396,8 @@
     word = mb_progm_next_word(progm, &start, &playing);
     mb_visibility_new(VIS_HIDDEN, bang->root_coord, word);
 
+    mb_subtree_free_new(bang->root_coord, word);
+
     mb_progm_free_completed(progm);
 
     /*! \todo Remove bang when program is completed.
--- a/include/mb_animate.h	Wed Nov 19 11:26:01 2008 +0800
+++ b/include/mb_animate.h	Wed Nov 19 20:53:40 2008 +0800
@@ -56,6 +56,8 @@
 				    paint_t *paint, mb_word_t *word);
 extern mb_action_t *mb_rotate_new(float angle1, float angle2,
 				  coord_t *coord, mb_word_t *word);
+extern mb_action_t *mb_subtree_free_new(coord_t *coord,
+					mb_word_t *word);
 
 enum { VIS_VISIBLE, VIS_HIDDEN };
 extern mb_action_t *mb_visibility_new(int visib, coord_t *coord,
--- a/src/Makefile.am	Wed Nov 19 11:26:01 2008 +0800
+++ b/src/Makefile.am	Wed Nov 19 20:53:40 2008 +0800
@@ -4,7 +4,10 @@
 
 noinst_PROGRAMS = X_main
 
-libmbfly_la_SOURCES = animate.c chgcolor.c coord.c event.c geo.c observer.c paint.c redraw_man.c rotate.c shape_path.c shape_rect.c shape_text.c shift.c timer.c timertool.c tools.c visibility.c X_supp.c
+libmbfly_la_SOURCES = animate.c chgcolor.c coord.c event.c geo.c	\
+	observer.c paint.c redraw_man.c rotate.c shape_path.c		\
+	shape_rect.c shape_text.c shift.c subtree_free.c timer.c 	\
+	timertool.c tools.c visibility.c X_supp.c
 libmbfly_la_CPPFLAGS = @cairo_CFLAGS@
 libmbfly_la_LDFLAGS = @cairo_LIBS@
 
--- a/src/animate.c	Wed Nov 19 11:26:01 2008 +0800
+++ b/src/animate.c	Wed Nov 19 20:53:40 2008 +0800
@@ -127,6 +127,10 @@
 #ifndef UNITTEST
     factory = rdman_get_ob_factory(rdman);
     progm->complete = subject_new(factory, progm, OBJT_PROGM);
+    if(progm->complete == NULL) {
+	free(progm);
+	return NULL;
+    }
 #endif /* UNITTEST */
 
     progm->n_words = 0;
--- a/src/observer.c	Wed Nov 19 11:26:01 2008 +0800
+++ b/src/observer.c	Wed Nov 19 20:53:40 2008 +0800
@@ -51,6 +51,7 @@
 void subject_notify(subject_t *subject, event_t *evt) {
     ob_factory_t *factory = subject->factory;
     observer_t *observer;
+    subject_t *old_subject;
 
     evt->tgt = subject;
     while(subject) {
@@ -69,15 +70,16 @@
 	}
 
 	subject->flags &= ~SUBF_BUSY;
-	if(subject->flags & SUBF_FREE)
-	    subject_free(subject);
+
+	old_subject = subject;
+	subject = factory->get_parent_subject(factory, subject);
 
-	if(subject->flags & SUBF_STOP_PROPAGATE)
+	if(old_subject->flags & SUBF_FREE)
+	    subject_free(old_subject);
+
+	if(old_subject->flags & SUBF_STOP_PROPAGATE)
 	    break;
-
-	subject = factory->get_parent_subject(factory, subject);
     }
-
 }
 
 observer_t *subject_add_observer(subject_t *subject,
--- a/src/redraw_man.c	Wed Nov 19 11:26:01 2008 +0800
+++ b/src/redraw_man.c	Wed Nov 19 20:53:40 2008 +0800
@@ -613,6 +613,24 @@
     return OK;
 }
 
+static _rdman_coord_free_members(redraw_man_t *rdman, coord_t *coord) {
+    geo_t *member;
+    shape_t *shape;
+    int r;
+
+    FORMEMBERS(coord, member) {
+	shape = geo_get_shape(member);
+	r = rdman_shape_free(rdman, shape);
+	if(r != OK)
+	    return ERR;
+    }
+    return OK;
+}
+
+/*! \brief Free descendant coords and shapes of a coord.
+ *
+ * The specified coord is also freed.
+ */
 int rdman_coord_subtree_free(redraw_man_t *rdman, coord_t *subtree) {
     coord_t *coord, *prev_coord;
     int r;
@@ -625,6 +643,10 @@
 	coord != NULL;
 	coord = postorder_coord_subtree(subtree, coord)) {
 	if(!(prev_coord->flags & COF_FREE)) {
+	    r = _rdman_coord_free_members(rdman, prev_coord);
+	    if(r != OK)
+		return ERR;
+
 	    r = rdman_coord_free(rdman, prev_coord);
 	    if(r != OK)
 		return ERR;
@@ -632,6 +654,10 @@
 	prev_coord = coord;
     }
     if(!(prev_coord->flags & COF_FREE)) {
+	r = _rdman_coord_free_members(rdman, prev_coord);
+	if(r != OK)
+	    return ERR;
+
 	r = rdman_coord_free(rdman, prev_coord);
 	if(r != OK)
 	    return ERR;
--- a/src/shift.c	Wed Nov 19 11:26:01 2008 +0800
+++ b/src/shift.c	Wed Nov 19 20:53:40 2008 +0800
@@ -80,7 +80,7 @@
 
     shift = (mb_shift_t *)malloc(sizeof(mb_shift_t));
     if(shift == NULL)
-	return (mb_action_t *)shift;
+	return NULL;
 
     shift->x = x;
     shift->y = y;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/subtree_free.c	Wed Nov 19 20:53:40 2008 +0800
@@ -0,0 +1,50 @@
+#include "mb_redraw_man.h"
+#include "mb_animate.h"
+
+struct _subtree_free {
+    mb_action_t action;
+
+    coord_t *coord;
+};
+
+typedef struct _subtree_free subtree_free_t;
+
+void mb_subtree_free_start(mb_action_t *action,
+			   const mb_timeval_t *now,
+			   const mb_timeval_t *playing_time,
+			   redraw_man_t *rdman) {
+    subtree_free_t *sfree = (subtree_free_t *)action;
+
+    rdman_coord_subtree_free(rdman, sfree->coord);
+}
+
+void mb_subtree_free_step(mb_action_t *act, const mb_timeval_t *now,
+			  redraw_man_t *rdman) {
+}
+
+void mb_subtree_free_stop(mb_action_t *act, const mb_timeval_t *now,
+			  redraw_man_t *rdman) {
+}
+
+void mb_subtree_free_free(mb_action_t *act) {
+    free(act);
+}
+
+mb_action_t *mb_subtree_free_new(coord_t *coord,
+				 mb_word_t *word) {
+    subtree_free_t *sfree;
+
+    sfree = (subtree_free_t *)malloc(sizeof(subtree_free_t));
+    if(sfree == NULL)
+	return NULL;
+
+    sfree->action.start = mb_subtree_free_start;
+    sfree->action.step = mb_subtree_free_step;
+    sfree->action.stop = mb_subtree_free_stop;
+    sfree->action.free = mb_subtree_free_free;
+    sfree->coord = coord;
+
+    mb_word_add_action(word, (mb_action_t *)sfree);
+
+    return (mb_action_t *)sfree;
+}