あおきです。

  In mail "[ruby-ext:01219] Re: about ruby-gtk rewrite"
    じぶん wrote:

> > > Tree とか Ctree のメソッド追加/修正が いくつか あるんですけど、
> > > パッチ出していいでしょうか?
> > 
> > 構いません。
> 
> じゃ出します。

> 3  同じ GtkCTreeNode に対しては同じ Ruby オブジェクトを
>    返すようにした

ぬあー すみません。これバグってます。なんかすんなり通ったなーと
思ったら、make 後インストールしてなかっただけでした  (__;;
やっぱり独自に管理しなきゃいかんのですね…。
rbgtkctree.c の作りなおしたのを出し直します。

GTK_CTREE_ROW(node)->row を直接いじってるのがよろしくないんですが、
ノードからはツリーが得られないので仕方ないですね…。
-------------------------------------------------------------------
あおきみねろう

--- org.rbgtkctree.c Tue Aug 22 18:40:54 2000 +++ rbgtkctree.c Tue Aug 22 22:10:44 2000 @@ -13,24 +13,76 @@ #include "global.h" -static ID id_nodelist; +static ID id_ctndata; +static VALUE nodevalues; static void -ctree_node_mark(node) - GtkCTreeNode *node; +ctree_node_free(node) + void *node; { - if (node) - if (GTK_CTREE_ROW(node)) - if (GTK_CTREE_ROW(node)->row.data) - rb_gc_mark_maybe(GTK_CTREE_ROW(node)->row.data); + /* dummy */ +} + +static void +check_ctree_node(val) + VALUE val; +{ + Check_Type(val, T_DATA); + if (RDATA(val)->dmark != 0 || + RDATA(val)->dfree != ctree_node_free) + rb_raise(rb_eTypeError, + "wrong type %s (expecting Gtk::CTreeNode)", + rb_class2name(CLASS_OF(val))); +} + +static void +addvrel(v) + VALUE v; +{ + long l; + l = ((unsigned long)v) >> 2; + rb_hash_aset(nodevalues, INT2FIX(l), v); +} + +static void +delvrel(data) + gpointer data; +{ + VALUE v = (VALUE)data; + + if (v && !NIL_P(v)) { /* must be true */ + long l; + l = ((unsigned long)v) >> 2; + rb_hash_aset(nodevalues, INT2FIX(l), Qnil); + RDATA(v)->data = 0; + } } VALUE make_ctree_node(node) GtkCTreeNode* node; { + VALUE v; + if (!node) return Qnil; - return Data_Wrap_Struct(gCTreeNode, ctree_node_mark, 0, node); + v = Data_Wrap_Struct(gCTreeNode, 0, ctree_node_free, node); + addvrel(v); + GTK_CTREE_ROW(node)->row.data = (gpointer)v; + GTK_CTREE_ROW(node)->row.destroy = delvrel; + + return v; +} + +static VALUE +get_value_from_ctree_node(node) + GtkCTreeNode *node; +{ + if (!GTK_CTREE_ROW(node)) /* maybe freed */ + return Qnil; + if (GTK_CTREE_ROW(node)->row.data) + return (VALUE)GTK_CTREE_ROW(node)->row.data; + else + return make_ctree_node(node); } static GtkCTreeNode* @@ -40,17 +92,15 @@ GtkCTreeNode* c_node; if (NIL_P(node)) return NULL; + check_ctree_node(node); Data_Get_Struct(node, GtkCTreeNode, c_node); - return c_node; -} + /* + This does not work because we cannot get CTree from CTreeNode -static void -bind_ctree_node(ctree, node) - VALUE ctree, node; -{ - VALUE nodelist; - nodelist = rb_ivar_get(ctree, id_nodelist); - rb_ary_push(nodelist, node); + if (!c_node) + rb_raise(rb_eArgError, "freed Gtk::CTreeNode"); + */ + return c_node; } /* @@ -68,7 +118,6 @@ VALUE self, titles, tree_column; { GtkWidget *widget; - VALUE nodelist; if (TYPE(titles) == T_ARRAY) { char **buf; @@ -85,9 +134,6 @@ } set_widget(self, widget); - nodelist = rb_ary_new(); - rb_ivar_set(self, id_nodelist, nodelist); - return Qnil; } @@ -211,7 +257,7 @@ while (c_node) { tmp = GTK_CTREE_ROW(c_node)->sibling; - ctree_post_recursive(self, make_ctree_node(c_node)); + ctree_post_recursive(self, get_value_from_ctree_node(c_node)); c_node = tmp; } @@ -260,7 +306,8 @@ if (c_node && GTK_CTREE_ROW(c_node)->level <= c_depth) { while (c_node) { tmp = GTK_CTREE_ROW(c_node)->sibling; - ctree_post_recursive_to_depth(self, make_ctree_node(c_node), depth); + ctree_post_recursive_to_depth(self, + get_value_from_ctree_node(c_node), depth); c_node = tmp; } } @@ -300,7 +347,7 @@ while (c_node) { tmp = GTK_CTREE_ROW(c_node)->sibling; - ctree_pre_recursive(self, make_ctree_node(c_node)); + ctree_pre_recursive(self, get_value_from_ctree_node(c_node)); c_node = tmp; } @@ -348,7 +395,7 @@ if (c_node && GTK_CTREE_ROW(c_node)->level <= c_depth) { while (c_node) { tmp = GTK_CTREE_ROW(c_node)->sibling; - ctree_pre_recursive_to_depth(self, make_ctree_node(c_node), depth); + ctree_pre_recursive_to_depth(self, get_value_from_ctree_node(c_node), depth); c_node = tmp; } } @@ -394,7 +441,7 @@ result = gtk_ctree_last(GTK_CTREE(get_widget(self)), get_ctree_node(node)); - return make_ctree_node(result); + return get_value_from_ctree_node(result); } /* @@ -1116,15 +1163,15 @@ * node - tree node. * data - custom data associated with a node. */ + +static VALUE ctreenode_set_data _((VALUE, VALUE)); + static VALUE ctree_node_set_row_data(self, node, data) VALUE self, node, data; { - gtk_ctree_node_set_row_data(GTK_CTREE(get_widget(self)), - get_ctree_node(node), - (gpointer)data); - bind_ctree_node(self, node); - return self; + check_ctree_node(node); + return ctreenode_set_data(node, data); } /* @@ -1135,12 +1182,15 @@ * argument: * node - tree node. */ + +static VALUE ctreenode_get_data _((VALUE)); + static VALUE ctree_node_get_row_data(self, node) VALUE self, node; { - return (VALUE)gtk_ctree_node_get_row_data(GTK_CTREE(get_widget(self)), - get_ctree_node(node)); + check_ctree_node(node); + return ctreenode_get_data(node); } /* @@ -1297,7 +1347,7 @@ result = gtk_ctree_node_nth(GTK_CTREE(get_widget(self)), NUM2INT(row)); - return make_ctree_node(result); + return get_value_from_ctree_node(result); } static VALUE @@ -1326,7 +1376,7 @@ GtkCTreeNode* node; node = GTK_CTREE_NODE(sellist->data); sellist = sellist->next; - rb_yield(make_ctree_node(node)); + rb_yield(get_value_from_ctree_node(node)); } return Qnil; @@ -1351,7 +1401,8 @@ ctreenode_get_next(self) VALUE self; { - return make_ctree_node(GTK_CTREE_NODE_NEXT(get_ctree_node(self))); + GtkCTreeNode *result = GTK_CTREE_NODE_NEXT(get_ctree_node(self)); + return get_value_from_ctree_node(result); } /* @@ -1361,7 +1412,8 @@ ctreenode_get_prev(self) VALUE self; { - return make_ctree_node(GTK_CTREE_NODE_PREV(get_ctree_node(self))); + GtkCTreeNode *result = GTK_CTREE_NODE_PREV(get_ctree_node(self)); + return get_value_from_ctree_node(result); } /* @@ -1372,7 +1424,7 @@ VALUE self; { GtkCTreeNode* result = GTK_CTREE_ROW(get_ctree_node(self))->parent; - return make_ctree_node(result); + return get_value_from_ctree_node(result); } /* @@ -1383,7 +1435,7 @@ VALUE self; { GtkCTreeNode *result = GTK_CTREE_ROW(get_ctree_node(self))->sibling; - return make_ctree_node(result); + return get_value_from_ctree_node(result); } /* @@ -1394,7 +1446,7 @@ VALUE self; { GtkCTreeNode *result = GTK_CTREE_ROW(get_ctree_node(self))->children; - return make_ctree_node(result); + return get_value_from_ctree_node(result); } /* @@ -1405,7 +1457,7 @@ VALUE self; { GtkCTreeNode* node = get_ctree_node(self); - return (GTK_CTREE_ROW(node)->is_leaf)?Qtrue:Qfalse; + return (GTK_CTREE_ROW(node)->is_leaf) ? Qtrue : Qfalse; } /* @@ -1419,13 +1471,30 @@ return (GTK_CTREE_ROW(node)->expanded)?Qtrue:Qfalse; } +/* + * CTreeNode#data, data= + */ +static VALUE +ctreenode_get_data(node) + VALUE node; +{ + return rb_ivar_get(node, id_ctndata); +} + +static VALUE +ctreenode_set_data(node, data) + VALUE node, data; +{ + rb_ivar_set(node, id_ctndata, data); + return data; +} + + void Init_gtk_ctree() { gCTree = rb_define_class_under(mGtk, "CTree", gCList); gCTreeNode = rb_define_class_under(mGtk, "CTreeNode", rb_cData); - id_nodelist = rb_intern("nodelist"); - /* constants */ /* @@ -1561,10 +1630,18 @@ rb_define_method(gCTree, "sort_node", ctree_sort_node, 1); rb_define_method(gCTree, "sort_recursive", ctree_sort_recursive, 1); rb_define_method(gCTree, "node_nth", ctree_node_nth, 1); + rb_define_method(gCTree, "[]", ctree_node_nth, 1); rb_define_method(gCTree, "set_show_stub", ctree_set_show_stub, 1); rb_define_method(gCTree, "each_selection", ctree_each_selection, 0); rb_define_method(gCTree, "tree_column", ctree_get_tree_column, 0); + + /* CTreeNode */ + id_ctndata = rb_intern("gtk_ctree_node_data"); + nodevalues = Qnil; + rb_global_variable(&nodevalues); + nodevalues = rb_hash_new(); + rb_define_method(gCTreeNode, "next", ctreenode_get_next, 0); rb_define_method(gCTreeNode, "prev", ctreenode_get_prev, 0); rb_define_method(gCTreeNode, "parent", ctreenode_get_parent, 0); @@ -1572,4 +1649,6 @@ rb_define_method(gCTreeNode, "children", ctreenode_get_children, 0); rb_define_method(gCTreeNode, "leaf?", ctreenode_is_leaf, 0); rb_define_method(gCTreeNode, "expanded?", ctreenode_expanded, 0); + rb_define_method(gCTreeNode, "data", ctreenode_get_data, 0); + rb_define_method(gCTreeNode, "data=", ctreenode_set_data, 1); }