# HG changeset patch # User Thinker K.F. Li # Date 1282704030 -28800 # Node ID d8764f10e141359b603308cda114ccc46ae888b5 # Parent 00a8c8a9e157262b11b836f0d337009d1210d0d7 Remove a coord from the tree in JS diff -r 00a8c8a9e157 -r d8764f10e141 nodejs/coord.cc --- 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 self) { + Handle *child_hdl; + Handle *mem_hdl; + redraw_man_t *rdman; + coord_t *coord, *child; + shape_t *mem; + Handle _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 *)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 *)mb_prop_get(&mem->obj.props, + PROP_JSOBJ); + WRAP(*mem_hdl, NULL); + SET(*mem_hdl, "valid", _false); + } + } +} + static void xnjsmb_coord_mod(Handle self, coord_t *coord) { Persistent *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 self, const char **err) { + Handle 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. diff -r 00a8c8a9e157 -r d8764f10e141 nodejs/coord.m4 --- 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])))