あおきです。

  In mail "[ruby-ext:01217] Re: about ruby-gtk rewrite"
    Hiroshi IGARASHI <igarashi / ueda.info.waseda.ac.jp> wrote:

> いがらしです。

> > talk とか見てると ruby-gtk はかなり書き直されてるみたいですが、
> > 0.23 から(直接)続くものはもうなくなるんでしょうか?
> 
> (分離して開発している)rewrite版のはまだかかりそうなので、
> 今のruby-gtkに基づく最後(にしたいなぁ)のバージョン0.24を
> 出そうと思っています。

了解しました。


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

じゃ出します。

1  Gtk::TreeItem に subtree() subtree=() expanded? leaf? を追加

たしかまだ追加されてないと思うんですが…。
内容はたいしたことないので問題ないと思います。


2  gtk_object_list を st_table に変更

これはこういうこと(↓)されたときに

class Bignum
  def hash() 0 end
  def eql?() true end
end

落ちないようにするためです。それにこの方がちょい速い。

ついでに gtk_object_list を static にしちゃいました。
まずければ戻してください。


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

同時に ctree.node_set_row_data はインスタンス変数として
保持することにして、ctnode.data で参照できるようにも
してあります。

node_* でのノードのタイプチェックもつけました。でないと

    ctree.node_set_text Time.now, 1, 'string'

のように Data を渡したときに落ちます。
(これはもしかして他のところでもそうなのか?)

本当は CTreeNode#tree もつけて CTree#node_* は全部 CTreeNode の
メソッドに移したいところですが、変更がでかすぎるのでしてません。
ツリーを得る方法も力技しか思いつかない。


> > 0.23 由来のパッチではもはや通らない可能性もありますよね…。
> 
> まあsnapshot見ればお分かりの通り0.23からほとんどいじってないので
> 多分大丈夫でしょう。だめでも頑張って手で当てます;-)

え、スナップショット出てるんですか?
「現在は正式バージョンが最新です」って ruby-lang.org に
書いてあったから出てないのかと思ってました。
-------------------------------------------------------------------
あおきみねろう

2000-08-22 20:50:36 Minero Aoki <aamine / dp.u-netsurf.ne.jp> * src/rbgtkitem.c: Gtk::TreeItem#subtree, subtree=, expanded?, leaf? * src/rbgtk.c: gtk_object_list is a st_table. * src/global.h: now gtk_object_list is not extern. * src/rbgtkctree.c: uses get_value_from_gobject() instead of make_ctree_node(). checkes type of CTreeNode. Gtk::CTree#[]
--- org.rbgtk.c Tue Aug 22 18:30:07 2000 +++ rbgtk.c Tue Aug 22 18:07:23 2000 @@ -12,11 +12,11 @@ ************************************************/ #include "global.h" +#include "st.h" #ifdef HAVE_SYS_TIME_H # include <sys/time.h> #endif -VALUE gtk_object_list; VALUE mGtk; VALUE gObject; VALUE gWidget; @@ -114,6 +114,9 @@ VALUE mRC; +static st_table *gtk_object_list; +static VALUE gtk_object_list_v; + static ID id_gtkdata; static ID id_relatives; static ID id_call; @@ -162,7 +165,8 @@ { struct RData *data; - rb_hash_aset(gtk_object_list, INT2NUM(obj), Qnil); + if (!st_delete(gtk_object_list, (char**)&obj, 0)) + rb_bug("ruby-gtk: already freed object is freed again"); data = RDATA(rb_ivar_get(obj, id_gtkdata)); data->dfree = 0; data->data = 0; @@ -174,6 +178,7 @@ GtkObject *gtkobj; { VALUE data; + st_table *tbl; data = Data_Wrap_Struct(rb_cData, gobj_mark, 0, gtkobj); gtk_object_set_user_data(gtkobj, (gpointer)obj); @@ -183,7 +188,7 @@ rb_ivar_set(obj, id_gtkdata, data); gtk_signal_connect(gtkobj, "destroy", (GtkSignalFunc)delete_gobject, (gpointer)obj); - rb_hash_aset(gtk_object_list, INT2NUM(obj), obj); + st_add_direct(gtk_object_list, (char*)obj, (char*)obj); } static VALUE @@ -2474,8 +2479,12 @@ void Init_gtk_gtk() { - gtk_object_list = rb_hash_new(); - rb_global_variable(&gtk_object_list); + gtk_object_list_v = Qnil; + rb_global_variable(&gtk_object_list_v); + gtk_object_list = st_init_numtable(); + gtk_object_list_v = Data_Wrap_Struct(rb_cObject, + rb_mark_tbl, st_free_table, + gtk_object_list); /* IDs */ id_gtkdata = rb_intern("gtkdata");
--- org.global.h Tue Aug 22 18:33:01 2000 +++ global.h Tue Aug 22 18:04:20 2000 @@ -33,7 +33,6 @@ extern VALUE mRC; extern VALUE mGtk; -extern VALUE gtk_object_list; extern VALUE gObject; extern VALUE gWidget; extern VALUE gContainer;
--- src/orig.rbgtkitem.c Mon Aug 21 06:38:38 2000 +++ src/rbgtkitem.c Mon Aug 21 06:49:06 2000 @@ -393,6 +393,36 @@ } static VALUE +titem_subtree(self) + VALUE self; +{ + GtkWidget *t; + + t = GTK_TREE_ITEM_SUBTREE(GTK_TREE_ITEM(get_widget(self))); + return t ? get_value_from_gobject(GTK_OBJECT(t)) : Qnil; +} + +static VALUE +titem_leaf_p(self) + VALUE self; +{ + GtkWidget *t; + + t = GTK_TREE_ITEM_SUBTREE(GTK_TREE_ITEM(get_widget(self))); + return t ? Qtrue : Qfalse; +} + +static VALUE +titem_expanded_p(self) + VALUE self; +{ + GtkTreeItem *i; + + i = GTK_TREE_ITEM(get_widget(self)); + return i->expanded ? Qtrue : Qfalse; +} + +static VALUE titem_select(self) VALUE self; { @@ -433,6 +463,10 @@ rb_define_method(gTreeItem, "initialize", titem_initialize, -1); rb_define_method(gTreeItem, "set_subtree", titem_set_subtree, 1); + rb_define_method(gTreeItem, "subtree=", titem_set_subtree, 1); + rb_define_method(gTreeItem, "subtree", titem_subtree, 0); + rb_define_method(gTreeItem, "leaf?", titem_leaf_p, 0); + rb_define_method(gTreeItem, "expanded?", titem_expanded_p, 0); rb_define_method(gTreeItem, "select", titem_select, 0); rb_define_method(gTreeItem, "deselect", titem_deselect, 0); rb_define_method(gTreeItem, "expand", titem_expand, 0);
--- org.rbgtkctree.c Tue Aug 22 18:40:54 2000 +++ rbgtkctree.c Tue Aug 22 20:39:32 2000 @@ -13,16 +13,25 @@ #include "global.h" -static ID id_nodelist; +static ID id_ctndata; 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))); } VALUE @@ -30,7 +39,7 @@ GtkCTreeNode* node; { if (!node) return Qnil; - return Data_Wrap_Struct(gCTreeNode, ctree_node_mark, 0, node); + return Data_Wrap_Struct(gCTreeNode, 0, ctree_node_free, node); } static GtkCTreeNode* @@ -40,17 +49,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 +75,6 @@ VALUE self, titles, tree_column; { GtkWidget *widget; - VALUE nodelist; if (TYPE(titles) == T_ARRAY) { char **buf; @@ -85,9 +91,6 @@ } set_widget(self, widget); - nodelist = rb_ary_new(); - rb_ivar_set(self, id_nodelist, nodelist); - return Qnil; } @@ -211,7 +214,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_gobject(GTK_OBJECT(c_node))); c_node = tmp; } @@ -260,7 +263,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_gobject(GTK_OBJECT(c_node)), depth); c_node = tmp; } } @@ -300,7 +304,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_gobject(GTK_OBJECT(c_node))); c_node = tmp; } @@ -348,7 +352,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_gobject(GTK_OBJECT(c_node)), depth); c_node = tmp; } } @@ -394,7 +398,7 @@ result = gtk_ctree_last(GTK_CTREE(get_widget(self)), get_ctree_node(node)); - return make_ctree_node(result); + return get_value_from_gobject(GTK_OBJECT(result)); } /* @@ -1116,15 +1120,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 +1139,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 +1304,7 @@ result = gtk_ctree_node_nth(GTK_CTREE(get_widget(self)), NUM2INT(row)); - return make_ctree_node(result); + return get_value_from_gobject(GTK_OBJECT(result)); } static VALUE @@ -1326,7 +1333,7 @@ GtkCTreeNode* node; node = GTK_CTREE_NODE(sellist->data); sellist = sellist->next; - rb_yield(make_ctree_node(node)); + rb_yield(get_value_from_gobject(GTK_OBJECT(node))); } return Qnil; @@ -1351,7 +1358,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_gobject(GTK_OBJECT(result)); } /* @@ -1361,7 +1369,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_gobject(GTK_OBJECT(result)); } /* @@ -1372,7 +1381,7 @@ VALUE self; { GtkCTreeNode* result = GTK_CTREE_ROW(get_ctree_node(self))->parent; - return make_ctree_node(result); + return get_value_from_gobject(GTK_OBJECT(result)); } /* @@ -1383,7 +1392,7 @@ VALUE self; { GtkCTreeNode *result = GTK_CTREE_ROW(get_ctree_node(self))->sibling; - return make_ctree_node(result); + return get_value_from_gobject(GTK_OBJECT(result)); } /* @@ -1394,7 +1403,7 @@ VALUE self; { GtkCTreeNode *result = GTK_CTREE_ROW(get_ctree_node(self))->children; - return make_ctree_node(result); + return get_value_from_gobject(GTK_OBJECT(result)); } /* @@ -1405,7 +1414,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 +1428,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 +1587,15 @@ 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"); + 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 +1603,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); }