Gtk+ の OCaml バインディングである lablgtk2 用の新しいウィジェットのファミリを作成しています。これらのウィジェットの中には、かなり複雑な情報を編集または表示できるものがあります。そのため、GTree
モジュールで見られるものと同様に、model-view-controler または subject-observer の使用に興味があります。
このモジュールはGTree.model
とGTree.view
クラスを定義します。それぞれに接続可能なシグナルがあり、GTree.model
は 1 つ以上GTree.view
の に接続できます。
ライブラリで利用可能なコードは C ライブラリのバインディングであるため、純粋な OCaml でこの構成を模倣することはそれほど簡単ではありません。次の手順を実行する必要があります。
- 新しいウィジェットの定義
- 新しいシグナルの定義
- これらの新しいシグナルのトリガー
- 新しいモデルの定義
1 と 2 は実行できますが、3 と 4 の実行方法がわかりません。これらを正しく実行するにはどうすればよいですか?
新しいウィジェットの定義
新しいウィジェットの定義自体は問題ありません。新しいウィジェットは、通常、Gnome キャンバスまたはコンポジットの特殊化されたバージョンです。前者の場合、新しいウィジェットは Gnome キャンバスから GObj.widget として継承でき、後者の場合、コンポジットを保持するために使用されるコンテナーによって提供される GObj.widget を使用できます。これは通常次のようになります
class view () =
let vbox = GPack.vbox () in
…
object(self)
inherit GObj.widget vbox#as_widget
…
end
新しいシグナルの定義
バインディングは、新しいシグナルを定義するコードの例を多数提供するため、次のスニペットで示されているように、パラメーターのないシグナルの単純なケースを考慮して、ウィジェットの新しいシグナルを定義できます。
open GtkSignal
module Event =
struct
let plop : ([>`widget], unit -> unit) t = {
name = "plop_event";
classe = `widget;
marshaller = marshal_unit;
}
let fizz : ([>`widget], unit -> unit) t = {
name = "fizz_event";
classe = `widget;
marshaller = marshal_unit;
}
end
class pill_signals obj =
object (self)
inherit ['a] GObj.gobject_signals (obj :> Gtk.widget Gobject.obj)
method plop = self#connect Event.plop
method fizz = self#connect Event.fizz
end
これらの定義により、ウィジェットは適切なメソッドview
を定義することでこれらのシグナルを公開できます。connect
method connect =
new pill_signals obj
新しいシグナルのトリガー
この関数GtkSignal.emit
は、オブジェクトに信号を送信し、登録されたコールバックをトリガーするという目的を果たしているようです。これは、次の署名として機能します。
val emit :
'a Gobject.obj ->
sgn:('a, 'b) GtkSignal.t ->
emitter:(cont:('c Gobject.data_set array -> 'd) -> 'b) ->
conv:(Gobject.g_value -> 'd) -> 'b
最初の 2 つのパラメーターは一目瞭然ですが、残りの 2 つのパラメーターが何であるかは明確ではありません。残念ながら、信号はコードの C 側から放出されるため、lablgtk ソース コードには使用例がありません。これらの 2 つの引数は、 として実体化されたシグナルの引数の準備と'c Gobject.data_set array
、 というラベルの付いた引数を使用して生成された値の取得に関連しているよう~conv
です。~cont
それにもかかわらず、エミッターでの - 引数の役割はまだ明確にする必要があります。
新しいモデルの定義
モデルの定義の難しい部分はGObj.object
、受信シグナルを送信できるようにするために継承する必要があることです。残念ながら、最小限の Gtk+ オブジェクトを直接定義できる関数はありません。私がこの方向に最も遠くまで行ったのは
module Model =
struct
let create () =
GtkObject.make ~classe:"GObject" []
end
let model () =
new model (Model.create ())
関数を呼び出してmodel
対応するオブジェクトをインスタンス化すると、次のメッセージが表示されます。
Gtk-CRITICAL **: IA__gtk_object_sink: アサーション 'GTK_IS_OBJECT (オブジェクト)' が失敗しました
明らかに、ここには怪しいものがあります。おそらく、パラメーター リスト (上記のスニペットの空のリスト) が小さすぎたのでしょう。