# HG changeset patch # User Thinker K.F. Li # Date 1282733207 -28800 # Node ID 56a5e08cd8afd4c3f17e93afe98d98d0cd1d816c # Parent d2f2ed27b84db066a358898566293b0ba18e8424 Make shapes can be removed from the tree diff -r d2f2ed27b84d -r 56a5e08cd8af nodejs/coord.cc --- a/nodejs/coord.cc Wed Aug 25 18:22:32 2010 +0800 +++ b/nodejs/coord.cc Wed Aug 25 18:46:47 2010 +0800 @@ -196,6 +196,7 @@ xnjsmb_coord_add_shape(coord_t *coord, Handle self, shape_t *shape, const char **err) { Handle js_rt; + Persistent *shape_hdl; redraw_man_t *rdman; int r; @@ -204,6 +205,11 @@ r = rdman_add_shape(rdman, shape, coord); if(r != 0) *err = "Unknown error"; + + /* see \ref jsgc */ + shape_hdl = (Persistent *)mb_prop_get(&shape->obj.props, + PROP_JSOBJ); + shape_hdl->ClearWeak(); } static void diff -r d2f2ed27b84d -r 56a5e08cd8af nodejs/shapes.cc --- a/nodejs/shapes.cc Wed Aug 25 18:22:32 2010 +0800 +++ b/nodejs/shapes.cc Wed Aug 25 18:46:47 2010 +0800 @@ -11,6 +11,8 @@ #define ASSERT(x) #endif +#define OK 0 + using namespace v8; /*! \defgroup xnjsmb_shapes JS binding for shapes. @@ -18,6 +20,29 @@ * * @{ */ +/*! \brief This function is called when GC collecting a shape. + * + * It was installed by Persistent::MakeWeak(). + */ +static void +xnjsmb_shape_recycled(Persistent obj, void *parameter) { + Persistent *self_hdl = (Persistent *)parameter; + Handle js_rt; + redraw_man_t *rdman; + shape_t *shape; + + shape = (shape_t *)UNWRAP(*self_hdl); + if(shape == NULL) + return; + + WRAP(*self_hdl, NULL); + + js_rt = GET(*self_hdl, "mbrt")->ToObject(); + rdman = xnjsmb_rt_rdman(js_rt); + rdman_shape_changed(rdman, shape); + rdman_shape_free(rdman, shape); +} + static void xnjsmb_shape_mod(Handle self, shape_t *sh) { Persistent *self_hdl; @@ -28,6 +53,8 @@ self_hdl = new Persistent(); *self_hdl = Persistent::New(self); mb_prop_set(&sh->obj.props, PROP_JSOBJ, self_hdl); + + self_hdl->MakeWeak(self_hdl, xnjsmb_shape_recycled); } static void @@ -102,6 +129,31 @@ } static void +xnjsmb_shape_remove(shape_t *sh, Handle self) { + Handle js_rt; + redraw_man_t *rdman; + Persistent *self_hdl; + int r; + + self_hdl = (Persistent *)mb_prop_get(&sh->obj.props, + PROP_JSOBJ); + + SET(*self_hdl, "valid", Boolean::New(0)); + WRAP(*self_hdl, NULL); + + js_rt = GET(*self_hdl, "mbrt")->ToObject(); + ASSERT(js_rt != NULL); + rdman = xnjsmb_rt_rdman(js_rt); + + rdman_shape_changed(rdman, sh); + r = rdman_shape_free(rdman, sh); + if(r != OK) + THROW_noret("Can not free a shape for unknown reason"); + + delete self_hdl; +} + +static void xnjsmb_sh_rect_set(shape_t *sh, Handle self, float x, float y, float w, float h, float rx, float ry) { Handle rt; diff -r d2f2ed27b84d -r 56a5e08cd8af nodejs/shapes.m4 --- a/nodejs/shapes.m4 Wed Aug 25 18:22:32 2010 +0800 +++ b/nodejs/shapes.m4 Wed Aug 25 18:46:47 2010 +0800 @@ -5,9 +5,11 @@ [xnjsmb_shape_stroke_width_get], [xnjsmb_shape_stroke_width_set])], [METHOD([show], [sh_show], (), 0, []), - METHOD([hide], [sh_hide], (), 0, [])]) + METHOD([hide], [sh_hide], (), 0, []), + METHOD([remove], [xnjsmb_shape_remove], (SELF), 0, [])]) -STRUCT([path], [shape_t], [], [], (([INHERIT], [shape]))) +STRUCT([path], [shape_t], [], [], + (([INHERIT], [shape]), ([STMOD], [xnjsmb_shape_mod]))) STRUCT([stext], [shape_t], [], [METHOD([set_text], [sh_stext_set_text], (STR([txt])), 1, []), diff -r d2f2ed27b84d -r 56a5e08cd8af nodejs/testcase.js --- a/nodejs/testcase.js Wed Aug 25 18:22:32 2010 +0800 +++ b/nodejs/testcase.js Wed Aug 25 18:46:47 2010 +0800 @@ -44,15 +44,25 @@ /* test removing a coord */ var rm_coord = mb_rt.coord_new(root); -var rm_rect = mb_rt.rect_new(150, 150, 50, 50, 10, 10); -paint.fill(rm_rect); -rm_coord.add_shape(rm_rect); +var rm_rect1 = mb_rt.rect_new(150, 150, 50, 50, 10, 10); +paint.fill(rm_rect1); +rm_coord.add_shape(rm_rect1); +var rm_rect2 = mb_rt.rect_new(100, 150, 50, 50, 10, 10); +paint.fill(rm_rect2); +rm_coord.add_shape(rm_rect2); setTimeout(function() { rm_coord.remove(); mb_rt.redraw_changed(); mb_rt.flush(); }, 3000); +/* test removing a shape */ +setTimeout(function() { + rm_rect1.remove(); + mb_rt.redraw_changed(); + mb_rt.flush(); + }, 2000); + /* Moving a path */ sys.puts(mb_rt.path_new); var path = mb_rt.path_new("m 100,50 L 120,50 L 200,150 L 180,150 z");