mikutterの最新の情報は、mikutter blogに引っ越しました。

2011年4月4日月曜日

新しいUIについて色々考えてる

考えてる途中のことを書き散らしてます。以下ただのつぶやきです。
現在のmikutterは、Gtkに完全に依存している。
例えばプラグイン内でGtkライブラリを叩いていたり。

もともと、guiプラグインがそういうものだったし、当たり前といえば当たり前のこと。というか、暗中模索の中、開発速度を稼ぐために意図的にやった部分がある。
ただ、最近いろんな環境で使われるようになって、様々な問題が出てきてしまった。

  1. Gtkが事実上使えない・使用に難がある環境(Mac OS、各種スマートフォン)では、mikutterが使えない
  2. あるRubyGtkやRubyのバージョンの組み合わせでは、それらのバグを踏んでSegmentation Faultになることがしょっちゅうあるらしく、作者自信が自虐ネタでふぁぼを稼ぐ深刻な事態へと発展している
  3. Gtkに強く依存しているために他のGUI Toolkit(Cocoa、Qt等)のバインディングを書きづらい
  4. 強いGtk依存のため、RubyGtkの知識がプラグイン開発の事実上の絶対条件となり、の敷居を上げている
Gtkをさも悪者のように書いているように見えるかもしれないけれど、最初にQtを選んでいたらこの部分がQtになっただけの話。安定したものを使っていれば2は無かったかもね。

で、じゃあいっそかなり開き直って、そこを抽象化してしまいませんか、という話。

どうするかというと、特定のルールに従ったデータ構造(DOM)を与えると、それをUIとしてレンダリングする、というもの。
例。
dom = [:vbox, [:label "hello"], [:button, {:id => :btn1}, "exit"] ]


とまあ、こういうありきたりなRubyのオブジェクトを

mui = mUi([:window, {:width => 320, :height => 240, :id => :main}])
mui << dom

とかすると、そういうウィンドウが表示されると。ご察しのとおりHTMLをめちゃくちゃ意識してます。
以下、mUi()は受け取った配列に色々Mixinとかをextendしまくって魔改造するものか、なんかでWrapして委譲するよなものだと思って読んでください。

Rubyの配列は、MIKU LangでS式として取り扱えます。つまり、windowとかlabelとかいう関数が定義されたコンテキストをつくってそこでこの式を評価すると。その関数の実装次第でQtにしたりCocoaにしたりできる、よね。
 MIKU Langでのコードでありデータのこと。ただの配列が実行出来るんだよ(Lisp)

実は、MUIというクラスを定義して、それの中身で別々のGUI Tool Kitを叩く計画は初期からあった。けどもういいや。先に上げたのとの違いは、それがクラスなのか、配列なのかというところ。配列にしておくことのメリットは:

  1. DOMが簡単に保存できる。なので、Gladeみたいなことが自然にできる
  2. Rubyのコアオブジェクトを使っているので、メソッドは誰でも知ってる
  3. JSONに翻訳可能なので、別プロセスに渡せる。
  4. だいたいどんなプログラミング言語にもありそうなデータ構造を使っているため、言語の壁を越えることが出来る
夢がひろがりんぐ\(^o^)/

1については、UI関連のコードがソースコードと分離できるので便利だと思う。そしてその形式はJSONとかYAMLとか、慣れ親しんだものでいける。

2については、例えば要素を追加したい時に、さてこのMUIオブジェクトにはaddか、appendか、何が実装されているのかな…おお、DOM意識してappendChildだったか…。みたいな時間が節約できる。
例の仮想コードの、「<<」にどん引きした人がいるかもしれないけれど、これはRubyユーザなら誰でも配列の末尾に値を追加するアレだということは知っている。+じゃだめですよ、あれは非破壊的だから。


3からはちょっとぶっ飛んでて、できたらいいなみたいな。Rubyでは現在完全なマルチスレッドは出来ない。RubyのThreadクラスは、実は時系列で切り替わってるだけなので、本当に同時に複数スレッドが動くわけじゃない。Ruby2.0ではそのあたりの事情が変わるらしいけれど、今でもプロセスを分けてしまえば並列に動かすことは出来る。Chromeとかあえてそうしてるしね。
プロセス間通信には、JSONが使える。S式が使いたかったんだけど、S式でHash表現するような魔改造すると、気軽に他のLispパーサでパースできなくなるので見送った。
つまり、mUiで魔改造されたオブジェクトは、変更が加えられると別のプロセスにそれを報告してレンダリングさせるようにも出来るよね、ということ。
ちょっとChromeって書いたけど、同じ利点と欠点をはらんでるね。例えばGtkがクラッシュしてもコアプロセスからmUiのプロセスを再起動してやればいいだけ。でもメモリ食いがち。

4についてはその応用で、向こうのプロセスがJSONを受け取ってそれをレンダリングしてくれるならば、Rubyで書かれてようが、Pythonで書かれてようが、JavaScript(!)で書かれてようが関係ないじゃない、という話。これが出来るということは、Rubyが使えない人でも、mikutterの別のUIバインディングを作れるかもしれない、ということ。

一応書いておくと、マルチプロセス化しますと言ってるわけじゃなくて、そういうこともできるね、という話。でも結構やる気。mikutter mobileあるで


イベント渡す方法とかは、DOMのアレでいいんじゃないかな普通に


mui.getElementById(:btn1).addEventListener(:click){ exit }

アツいなこれは。今の時代ならjQueryリスペクトしてもいいかも。DOMはW3Cがちゃんと規格化してた気がするから興味があったら調べてくだしあ、おれはあんなのよみたくない

なんかこういうのありそうで探してるんだけど、うーん。オススメあったら俺が愚かな車輪の再発明するのを止めていただけると嬉しいけれど…。

別プロジェクトでこういう事やってmikutterに取り込もうと思ってる。仕事終わったら詰めますね。