changeset 741:d8764f10e141

Remove a coord from the tree in JS
author Thinker K.F. Li <thinker@codemud.net>
date Wed, 25 Aug 2010 10:40:30 +0800
parents 00a8c8a9e157
children 24038e7a365b
files nodejs/coord.cc nodejs/coord.m4
diffstat 2 files changed, 64 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/nodejs/coord.cc	Wed Aug 25 10:07:33 2010 +0800
+++ b/nodejs/coord.cc	Wed Aug 25 10:40:30 2010 +0800
@@ -41,9 +41,15 @@
  * object added to the tree of a mbrt (runtime object), and remove the
  * reference and invalidate it when it being removed.
  *
- * The binding also hold a weak reference to every object, it free the
- * object when the callback of the weak reference being called and it
- * being valid.  If the object is invalid, the callback does nothing.
+ * For coords, they are always attached to the tree when it is valid.
+ * So, binding hold a persistent reference to it.  The reference is
+ * purged when a coord being removed from the tree and being
+ * invalidated.
+ *
+ * For any shape, it is not attached to the tree at begining, but is
+ * attached to a tree laterly, or is collected by GC.  The binding
+ * hold a weak reference for a new shape, and upgrade to a strong
+ * reference when the shape being added to the tree.
  */
 
 using namespace v8;
@@ -53,6 +59,44 @@
  *
  * @{
  */
+/*! \brief Invalidate JS objects for coords and shapes in a subtree.
+ *
+ * \param self is the object of the root of subtree.
+ *
+ * \sa \ref jsgc
+ */
+static void
+xnjsmb_coord_invalidate_subtree(Handle<Object> self) {
+    Handle<Object> *child_hdl;
+    Handle<Object> *mem_hdl;
+    redraw_man_t *rdman;
+    coord_t *coord, *child;
+    shape_t *mem;
+    Handle<Value> _false = Boolean::New(0);
+
+    if(!GET(self, "valid")->ToBoolean()->Value()) /* Invalidated object */
+	return;
+    
+    coord = (coord_t *)UNWRAP(self);
+    
+    /* Invalidate all coords in the subtree */
+    FOR_COORDS_PREORDER(coord, child) {
+	child_hdl = (Handle<Object> *)mb_prop_get(&child->obj.props,
+						   PROP_JSOBJ);
+	child = (coord_t *)UNWRAP(*child_hdl);
+	WRAP(*child_hdl, NULL);
+	SET(*child_hdl, "valid", _false);
+	
+	/* Invalidate members of a coord */
+	FOR_COORD_SHAPES(child, mem) {
+	    mem_hdl = (Handle<Object> *)mb_prop_get(&mem->obj.props,
+						    PROP_JSOBJ);
+	    WRAP(*mem_hdl, NULL);
+	    SET(*mem_hdl, "valid", _false);
+	}
+    }
+}
+
 static void
 xnjsmb_coord_mod(Handle<Object> self, coord_t *coord) {
     Persistent<Object> *self_hdl;
@@ -68,6 +112,7 @@
     subject = coord->mouse_event;
     subject_o = export_xnjsmb_auto_subject_new(subject);
     SET(self, "mouse_event", subject_o);
+    SET(self, "valid", Boolean::New(1));
 }
 
 static float
@@ -115,6 +160,20 @@
 	*err = "Unknown error";
 }
 
+static void
+xnjsmb_coord_remove(coord_t *coord, Handle<Object> self, const char **err) {
+    Handle<Object> js_rt;
+    redraw_man_t *rdman;
+
+    js_rt = GET(self, "mbrt")->ToObject();
+    rdman = xnjsmb_rt_rdman(js_rt);
+
+    xnjsmb_coord_invalidate_subtree(self);
+    
+    /* Free all coords and shapes in the subtree */
+    rdman_coord_free(rdman, coord);
+}
+
 #include "coord-inc.h"
 
 /*! \brief This function used by \ref xnjsmb_mb_rt to wrap coord object.
--- a/nodejs/coord.m4	Wed Aug 25 10:07:33 2010 +0800
+++ b/nodejs/coord.m4	Wed Aug 25 10:40:30 2010 +0800
@@ -1,7 +1,8 @@
 define([PROJ_PREFIX], [xnjsmb_auto_])dnl
 STRUCT([coord], [coord_t], [],
 	[METHOD([add_shape], [xnjsmb_coord_add_shape],
-		(SELF, OBJ([shape], [shape], [shape_t]), ERR), 1, [])],
+		(SELF, OBJ([shape], [shape], [shape_t]), ERR), 1, []),
+	 METHOD([remove], [xnjsmb_coord_remove], (SELF, ERR), 0, [])],
 	((GET_INDEX, (coord_get_index, NUMBER)),
 	 (SET_INDEX, (coord_set_index, NUMBER)),
 	 ([STMOD], [xnjsmb_coord_mod])))