稲地です。
今週はほとんど Ruby/GTK に手がつけられませんでした

----- Original Message -----
送信者 : Minoru Inachi <inachi / earth.interq.or.jp>
宛先 : ruby mailing list <ruby-list / netlab.co.jp>
送信日時 : 1999年7月3日 16:24
件名 : [ruby-list:15216] Re: Gtk::Menu の使い方に関する質問


> 稲地といいます。

> ----- Original Message -----
> 送信者 : Kazunori Akaishi <akaishi / master.cjn.ad.jp>
> 宛先 : ruby mailing list <ruby-list / netlab.co.jp>
> 送信日時 : 1999年7月2日 14:04
> 件名 : [ruby-list:15196] Re: Gtk::Menuの使い方に関する質問
>
>
> > akaishi です。
> >
> > From: Hiroshi Igarashi <igarashi / ueda.info.waseda.ac.jp>
> > Subject: [ruby-list:15195] Re: Gtk::Menu の使い方に関する質問
> > Date: Fri, 2 Jul 1999 13:42:20 +0900
> >
> > > > しかしTEST ボタンを押すとき、目に見えているのはメニューではなくてオ
プ
> ショ
> > > > ンメニュー(のみ)です。そしてどうやらラベルはメニューアイテムではなく
> (一
> > > > 時的に)オプションメニューに親がすげかえられている(?)ようです。
> > >
> > > このへん、私も昨晩GTK+のソースを見て確認しました。
> > > 一瞬Ruby/GTKのバグかと思いましたが、そうではないようです。
> > > #GTK+にNULLが渡ってしまうのはやっぱりバグか。
> >
> > MenuItem の child がとれないことの説明は上記で良いとして、
> >
> > > 宮木さんのスクリプトを上記のように書き換えた場合、
> > > opt.childrenは要素数1のArray [false]を返します。
> > > これは変ですね。Ruby/GTKのバグかもしれません。調べてみます。
> >
> > 自分のところでは動いているのになんでやー、と思って調べたところ、事前に
> > MenuItem の child を参照しているかしていないかで挙動が異なるようです。
> > 例えば、
> >
> > ['Item1','Item2','Item3'].each{|text|
> >   menuitem = Gtk::MenuItem.new(text)
> >   menuitem.child                       # この行を追加
> >   menu.append menuitem
> >   menuitem.show
> > }
> >
> > このようにしてやると、opt.children がちゃんと参照できます。
> > # Gtk+ の中で何らかの最適化機構が働いているのかも。
>
> このへんの原因はなんとなくわかってきたので、
> 後で ruby-ext に報告しておきます。

ということで、とりあえずの原因報告です。
GtkContainer.c の children を Ruby の配列要素に変換している
ところは rbgtkcontainer.c の 170 行目 にある cont_children_callback
です。

  static void
  cont_children_callback(widget, data)
      GtkWidget *widget;
      gpointer data;
  {
      VALUE ary = (VALUE)data;

      rb_ary_push(ary, get_value_from_gobject(GTK_OBJECT(widget)));
  }

ここで、get_value_from_gobject は rbgtk.c の 173 行目にあって、
GTK オブジェクトのプロパティ user_data を取り出しています。

  VALUE
  get_value_from_gobject(obj)
      GtkObject *obj;
  {
      return (VALUE)gtk_object_get_user_data(obj);
  }

ということは、その user_data に Ruby オブジェクトが
入っていなければならないことになります。
これをどこで入れているかというと、GTK オブジェクト
と対応する Ruby オブジェクトの関係を結ぶ set_gobject
(rbgtk.c の 147行目)で、これが動いていることが前提
となっていることが問題のようです。

  static void
  set_gobject(obj, gtkobj)
      VALUE obj;
      GtkObject *gtkobj;
  {
      VALUE data;

      data = Data_Wrap_Struct(rb_cData, gobj_mark, 0, gtkobj);
      gtk_object_set_user_data(gtkobj, (gpointer)obj);

GtkOptionMenu の子ウィジェットの add は GTK 内部で処理
されているので、Ruby/GTK の children を呼び出す段階では
対応する Ruby オブジェクトが作られていない可能性があります。
child を呼び出すと、対応する Ruby オブジェクトが作られるので、
children でも取り出せるようになるのでしょう。

---
稲地 稔 (e-mail: inachi / earth.interq.or.jp)