金曜日, 9月 25, 2009

OS X で IronRuby その2

前回の OS X で IronRuby その1 では、Windows.Forms を表示できるまで。

さて、今回はせっかくの IronRuby なので、Windows.Forms に黒魔術をかけてみる。

System::Windows::Forms::Form には、マウスを右クリックしたときにコンテキストメニューを表示させる ContextMenuStrip というプロパティがある。通常は、このコンテキストメニューにコマンドを実行するアイテム(ToolStripMenuItem) を登録して、アイテムがクリックされたら、イベントハンドラとしてコマンド処理を実行しましょうということになる。

こんな感じ。
$ vim winform_contextmenu.rb
 1 require 'System'
 2 require 'System.Windows.Forms'
 3
 4 Form = System::Windows::Forms::Form
 5 Application = System::Windows::Forms::Application
 6 MessageBox = System::Windows::Forms::MessageBox
 7 ContextMenuStrip = System::Windows::Forms::ContextMenuStrip
 8 ToolStripMenuItem = System::Windows::Forms::ToolStripMenuItem
 9
 10 class TestForm < Form
 11   def initialize
 12     self.Text = "Hello World Form"
 13    
 14     cms = ContextMenuStrip.new
 15     item = ToolStripMenuItem.new "hello"
 16     item.click { MessageBox.show "hello" }
 17     cms.items.add item
 18     self.ContextMenuStrip = cms
 19
 20   end
 21 end
 22
 23 Application.run TestForm.new



右クリックで表示されたコンテキストメニューの ”hello" をクリックしたら、メッセージボックスが表示される。

さて、ここから黒魔術へ。

まずは、コンテキストメニューを動的に変更するために、アイテムの登録方法を変えてみる。お試しとして、カレントディレクトリのファイル名を列挙して、そのファイル名をアイテム名として表示する。


$ vim winform_blackmagic.rb
 1     cms = ContextMenuStrip.new
 2     cms.opening do
 3       cms.items.clear
 4       Dir.glob("hoge_*.rb").each do |file|
 5         item = ToolStripMenuItem.new "#{file}"
 6         cms.items.add item
 7       end
 8     end
 9     self.ContextMenuStrip = cms

次のように空ファイルを作って
$ touch hoge_{1,2,3,4,5}.rb
 右クリックをすると、コンテキストメニューが表示される。



hoge_*.rb ファイルを一部削除すれば、右クリックのたびに、コンテキストメニューアイテムは減るし、追加すれば増える。

さて、次は黒魔術を実行できるように準備。hoge_*.rb は格好わるいので、わかりやすくするために、eval_*.rb に変えて、その名の通り、ファイルを読み込んで eval するイベントハンドラを登録する。


$ vim winform_blackmagic.rb
 1     cms = ContextMenuStrip.new
 2     cms.opening do
 3       cms.items.clear
 4       Dir.glob("eval_*.rb").each do |file|
 5         item = ToolStripMenuItem.new "#{file}"
 6         item.click do
 7           begin
 8             eval File.open(file) {|f| f.read}
 9           rescue Exception => e
 10             MessageBox.show e
 11           end
 12         end
 13         cms.items.add item
 14       end
 15     end
 16     self.ContextMenuStrip = cms

あとは、黒魔術の呪文ファイル(eval_*.rb)をそれぞれ用意するだけ。
試しに、 2つのファイルを用意してみた。

$ vim eval_msg.rb
 1 MessageBox.show "hello"

$ vim eval_add_button.rb
  1 self.text = "Hacked Form"
  2 @button = System::Windows::Forms::Button.new
  3 @button.text = "Hacked Button"
  4 @button.click { MessageBox.show "Hacked!!" }
  5 self.controls.add @button



eval_msg.rb を選択すると、メッセージダイアログが表示されて、eval_add_button.rb を選択すると、Form のタイトルがハックされて、ハックボタンが追加される。

これぞ IronRuby のスクリプトパワー。後付けで簡単にサクサクWindows.Formを拡張できる。

次回は、インタラクティブな Windows.Form 操作に挑戦してみようと考え中。

木曜日, 9月 24, 2009

OS X で Google Chrome その2

あぁ、悲しいことに、Google Reader が読めない・・・。
だめだこりゃ。

OS X で Google Chrome その1

OS X で IronRuby その1 から、もう20日がすぎてしまった・・・。
とりあえず、その2は置いといて、もうひとつのその1を。

会社の環境はすっかり Google Chrome に移行して、その速さに慣れて普通になった。まぁ、Delicious とか Evernote とか、Firefox アドオンが使えないのは不便だったりするけど、そのあたりは Bookmarklet や、時には Firefox を立ち上げて、運用でカバー(?)している。

そろそろ、うちの MacBook でも使ってみたいと思いつつ、OS X の安定版バイナリはなかなかリリースされない。ソースからビルドするのも大変だなーと思っていたら、どうも Early Access Release Channels から、開発版(Dev channel)の入手ができるとのこと。

ということで、Dev channel をダウンロードしてインストール。

さっそく起動してみると、Firefox/Safari の Bookmark とか 閲覧履歴を移行を確認するダイアログが表示された。

・・・と、ここでトラブル発生。移行がいつまでたっても完了しない。CPU ファンはブンブン唸っているし何かおかしい。top で調べてみると、Google Chrome と iavd というプロセスが CPU を占有してしまっている。

iavd は iAntiVirus のプロセスらしく、Protect my Mac のチェックを一時的に外してやると収まった。他のブログでも困っている人がいる模様。なんなんだろう。何か気持ち悪いなぁ、今度調べよう。

一方、Google Chrome の方は 100% のまま。うーん。仕方がないので、必殺の kill コマンド。

さて、気を取り直して、起動!





バージョンは、4.0.211.2。なんか怪しい動きは各所にあるものの、まぁ使えるかな。今後の安定化に期待。

ところで、結局、強制終了したので、Bookmark などの移行はできないまま・・・。ユーザ設定とかどこに保存されているんだろう。
Users/%USERNAME%/Library/Caches/ 
の下にはそれらしいものは無さげ。

ということで、続きはその2ということで。

木曜日, 9月 03, 2009

OS X で IronRuby その1

ひさしぶりのブログ。再開の第1号は開発ネタで。

OS X で IronRuby を動かして遊んでみようと、ちょっくら試行錯誤してみました。

まずは Mono の入手から。知らない間に 2.4 になってる。
ダウンロードページから、OS X Intel 用 Mono 2.4.2.3 Framework の dmg を落としてきて、インストールした後、動作確認。

$ vim hello.cs
  1 using System;
  2
  3 public class Program
  4 {
  5         static public void Main()
  6         {
  7             Console.WriteLine("hogehoge");
  8         }
  9 }
$ mcs hello.cs
$ mono hello.exe
hogehoge

ファイル名と出力が一致していないのはおいといて、
当然動くのを確認して、次は System.Windows.Forms の動作確認。

$ vim form.cs
  1 using System;
  2 using System.Windows.Forms;
  3
  4 public class Program
  5 {
  6     static public void Main()
  7     {
  8             Application.Run(new Hello());
  9     }
 10 }
 11
 12 public class Hello : Form
 13 {
 14         public Hello()
 15         {
 16                 Text = "Hello World";
 17         }
 18 }

$ mcs form.cs
form.cs(2,14): error CS0234: The type or namespace name `Windows' does not exist in the namespace `System'. Are you missing an assembly reference?
Compilation failed: 1 error(s), 0 warnings

shell returned 1

何にも考えずに実行したら怒られた・・・。

Mono Basics - Mono によると、
mcs hello.cs -pkg:dotnet ( .NET 1.1 アセンブリの場合)
gmcs hello.cs -pkg:dotnet (.NET 2.0 アセンブリの場合)
って書いてあるのに、実行してみると・・・

Package dotnet was not found in the pkg-config search path.
Perhaps you should add the directory containing `dotnet.pc'
to the PKG_CONFIG_PATH environment variable
No package 'dotnet' found
error CS8027: Error running pkg-config. Check the above output.

そんなパッケージ知らん、環境変数設定しろやと言われる。

うーん。dmg で導入したのに面倒だなぁ。
ひとまず、参照アセンブリを指定したら、コンパイルはできることがわかった。
$ mcs -r:System.Windows.Forms.dll form.cs
$ mono form.exe


ちょいと時間がかかってから、あっけなく表示された。

先ほどの PKG_CONFIG_PATH 環境変数について、dotnet.pc を含むパスを設定したらいいんちゃう?とあるので、検索。
$ find / -name "dotnet.pc"
/Library/Frameworks/Mono.framework/Versions/2.4.2.3/lib/pkgconfig/dotnet.pc

見つかったので、設定しておく。
$ vim ~/.profile
 export PKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/2.4.2.3/lib/pkgconfig
$ source ~/.profile

さて、もう一度やりなおし。
$ gmcs form.cs -pkg:dotnet
今度はコンパイルOK。これでアセンブリの指定は必要なくなった。


ということで、本題の IronRuby へ。

Ruby の .NET 実装である IronRuby の最新は、現在 0.9 。ダウンロードページから Zip ファイルを落としてきて展開して、最初のバージョン確認。
$ mono ../ironruby-0.9.0/bin/ir.exe -v
IronRuby 0.9.0.0 on .NET 2.0.0.0

お、とりあえず動いた。

$ mono ../ironruby-0.9.0/bin/ir.exe -e 'puts "hello"'
hello

ま、動くわな。じゃ、そろそろ IronRuby で System.Windows.Forms を動かすかー。
$ vim winform.rb
  1 require 'System'
  2 require 'System.Windows.Forms'
  3
  4 Form = System::Windows::Forms::Form
  5 Application = System::Windows::Forms::Application
  6
  7 class TestForm < Form
  8   def initialize
  9     self.Text = "Hello World Form"
 10   end
 11 end
 12
 13 Application.run TestForm.new

$ mono ../ironruby-0.9.0/bin/ir.exe winform.rb
で動きましたとさ。

・・・ということで、次回はもうちょっと IronRuby と Windows.Forms で遊んでみようかと。