The Green Shoes Manual 1.1.357

The Rules of Green Shoes

Green Shoesがどのように動作するのか推測するのはやめましょう。トリッキーな動作で悩むと思います。 私はShoesの中心的な規則を要約しまいた。これらは、それにすべての働きをさせるためには知らなくては ならないものです。

これらはGreen Shoesの至る所で目にする一般的な規則です。Green Shoesは単純さと明解さという 全体的な理念を持っていますが、いくつか勉強したり覚えたりする必要のあるポイントがあります。

Shoesのトリッキーなブロック

はい、これは極めて重要です。Green Shoesはブロックによってトリックをします。 このトリックはすべてのものを読みやすくします。しかし、これは深い階層でブロックを利用することを難しくもします。

普通のRubyブロックを試しましょう:

 Shoes.app do
   ary = ['potion', 'swords', 'shields']
   ary.each do |item|
     puts item
   end
 end

Green Shoesでは、これらの種類のブロックは同じ働きをします。この上記のブロックは配列をループして 各オブジェクトをitem変数に格納します。このitem変数はブロックが終わると消滅(スコープから出る)します。

考え方を守っているもう一つのことは、普通のRubyブロックの内部とselfを同じままにしています。 eachの前に呼ばれるどんなselfでも、それはeachブロック内部と同じです。

これらはどちらも大部分のGreen Shoesのブロックで正しいです。

 Shoes.app do
   stack do
     para "First"
     para "Second"
     para "Third"
   end
 end

ここでは二つのブロックがあります。一つ目はShoes.appによるものです。このappブロックはselfを変更します。

もう一方のブロックはstackブロックです。このブロックはselfを変更しません。

どんな理由があってappブロックはselfを変更するのでしょうか? 最後の例を徹底的に詳しく説明することから 始めましょう。

 Shoes.app do
   self.stack do
     self.para "First"
     self.para "Second"
     self.para "Third"
   end
 end

上記の例におけるすべてのselfはアプリケーションオブジェクトです。Shoesはappブロック内部でselfを 変更するために、Rubyのinstance_evalを利用します。そして、そのメソッドはstackを呼び出して paraをアプリケーションへ送ります。

これはShoesアプリケーション全体でインスタンス変数が利用できる理由でもあります:

 Shoes.app do
   @s = stack do
     @p1 = para "First"
     @p2 = para "Second"
     @p3 = para "Third"
   end
 end

これらのインスタンス変数は、すべてアプリケーションオブジェクト内部で終了します。

新しいウィンドウを作成するときはいつでも、selfも変更されます。

 Shoes.app title: "MAIN" do
   para self
   button "Spawn" do
     Shoes.app title: "CHILD" do
       para self
     end
   end
 end

ブロックリダイレクション

もっとも、stackブロックは別の話です。これはselfを変えませんし、基本的に標準のブロックです。

しかしトリックがあります:stackを配置してブロックを与えたとき、アプリケーションオブジェクトはstackを メモリへ配置します。ブロックが終了するときstackは立ち去ります。 そのため、アプリケーションのトップスロットから新しいstackまで、ブロック内部のすべての描画はリダイレクトされます。

そのため、まず、たとえ彼らが確かにアプリケーションオブジェクトへ渡したとしても、それらの3つのparastack上に描画されます。

 Shoes.app do
   stack do
     para "First"
     para "Second"
     para "Third"
   end
 end

少しトリッキーですよね?これについて知っていても噛みつかれるかもしれません。

それがあなたをつかまえる一つの方法は、appブロック外のプログラム内のどこか他で、stackを編集しようと することです。

例えばstackオブジェクトを使いまわすとしましょう。そして、そのオブジェクトを編集するクラスを持ちます。

 class Messenger
   def initialize slot
     @slot = slot
   end
   def add msg
     para msg rescue puts $!
   end
 end
 Shoes.app do
   slot = stack
   m = Messenger.new slot
   m.add 'hello'
 end

アプリケーションが始まるときに、stackオブジェクトをMessengerクラスへ渡すと仮定します。 そして、後で、メッセージが来るとき、addメソッドはそのstackにパラグラフを追加するのに用いられます。 正しく動作するでしょうか?

いや、それは動作しません。paraメソッドが見つかりません。すでにアプリケーションオブジェクトは まわりにありません。そして、それはparaメソッドによるものです。

幸いにも、それぞれのShoesオブジェクトはアプリケーションオブジェクトを再び開かせるappメソッドを 持っているため、さらなる編集ができます。

 class Messenger
   def initialize slot
     @slot = slot
   end
   def add msg
     @slot.app do
       para msg rescue puts $!
     end
   end
 end
 Shoes.app do
   slot = stack
   m = Messenger.new slot
   m.add 'hello'
 end

ご想像のとおり、そのappオブジェクトはselfをアプリケーションオブジェクトに変更します。

ルールは次のようになります:

1. "app"という名前か新しいウィンドウを作成するメソッドはアプリケーションオブジェクトのselfを変更します。
(これは、windowdialog同様に、Shoes.appとSlot.appの両方にとって正しいです。)
2. stackへ加えられるブロックは、フローや(追加などの)どんな操作メソッドでもselfを 変更しません。その代わりに、彼らはスロットをアプリケーションの編集stackにポップします。

固定された高さに注意

列でウィンドウを区切るように、スロットの固定された幅は重要です。

 Shoes.app do
   flow do
     stack :width => 200 do
       background lavender
       caption "Column one"
       para "is 200 pixels wide"
     end
     stack :width => -200 do
       background bisque
       caption "Column two"
       para "is 100% minus 200 pixels wide"
     end
   end
 end

スロットの固定された高さは、より一般的ではありません。通常は、テキストや画像がウィンドウの下へ できるだけ流れることを望みます。高さは通常は自然に決定します。

ここで重要なことは、固定された高さが実際はスロットに違うように振る舞わせることです。 確かに最後にはスロットは完全に切り離なされて、入れ子のウィンドウになります。 新しいレイヤーはオペレーティングシステムによってスロットを一定の正方形に保つために作成されます。

通常のスロットと入れ子ウィンドウのスロットとの違いは、後者はスクロールバーを持てることです。

 Shoes.app do
   stack width: 200, height: 200, scroll: true do
     background "#DFA"
     100.times do |i|
       para "Paragraph No. #{i}"
     end
     flush
   end
 end

これらの入れ子ウィンドウはより多くのメモリを必要とします。彼らはアプリケーションにもう少し負担をかけます。 もしあなたが、固定された高さのたくさんのスロットで遅さを経験しているなら、違うアプローチを試してください。

注意: 固定された高さのマジック(スロットを入れ子のウィンドウにする)は今のところGreen Shoesでは お試し版です。flush メソッドを追記する必要があります。

 Shoes.app do
   stack :width => 200 do
     background "#DFA"
     100.times do |i|
       para "Paragraph No. #{i}"
     end
   end
 end

画像と形状のブロック

多くの初心者が形状でウィンドウを散らかし始めます。すべての長方形や楕円形をスロットへ投げ入れるのは 確かに簡単です。

しかしながら、Shoesはそれらすべての形状のためにオブジェクトを生成することを覚えておいて下さい!。

 Shoes.app do
   fill black.push(0.1)
   100.times do |i|
     oval i, i, i * 2 if i > 0
   end
 end

この例では、100個の楕円形オブジェクトが生成されます。これは悪すぎるわけではありません。 しかし、一つの形状の中にこれらを作成するのなら、これはより軽量になるでしょう。

 # Not yet available
 Shoes.app do
   fill black(0.1)
   shape do
     100.times do |i|
       oval i, i, i * 2 if i > 0
     end
   end
 end

ああ、待ってください。この楕円形は今回は満たされません。なぜなら、この形状たちは一つの大きな形状に 結合されたからです。そして、このケースではShoesはどこを満たすべきか、分かりません。

そして、アウトラインを厳密に扱うとき、通常は一つの形状に結合することを望みます。

別のオプションでは、これらすべての楕円形を一つの画像に結合します。

 # Not yet available
 Shoes.app do
   fill black(0.1)
   image 300, 300 do
     100.times do |i|
       oval i, i, i * 2
     end
   end
 end

そうしよう!その楕円形はすべて一つの300 x 300の画像に結合されます。この場合では、その画像を メモリに保管するのは、おそらく100個の楕円形を持つよりはるかに大きくなるかもしれません。 しかし、何千もの形状を扱う場合には、イメージブロックはより安っぽくなる可能性があります。

ポイントは以下の通りです:画像やブロックへ形状をグループ化することは簡単ですので、もし速度を 得ようとするのなら、それを試してください。形状ブロックは特にメモリと速度を節約させるでしょう。

注意: 今のところGreen Shoesではこのマジック(複数の形状をグループにして一つの画像や形状にする) はサポートしていません。

どこでもUTF-8

Ruby自体はUnicodeを意識しません。そして、UTF-8は一種のUnicodeです。 (UTF-8の完全な説明はWikipediaを見てください。)

しかしながら、UTF-8はWEBで一般的です。そして、多くの異なったプラットホームがそれをサポートします。 そこで、Green Shoesがしなくてはならない変換の量を減らすために、Green Shoesはすべての文字列が UTF-8フォーマットであることを期待します。

すばらしいことに、Green ShoesでUTF-8を使えば無数の言語(ロシア語、日本語、スペイン語、英語)を 表示ことができます。テキストエディタでUTF-8を使用することだけを確認してください!

実例を示します:

 Shoes.app do
   stack :margin => 10 do
     @edit = edit_box do
       @para.text = @edit.text
     end
     @para = para ""
   end
 end

このアプリケーションは何でもコピーして編集ボックスに貼り付けて、Green Shoesパラグラフで表示することが できます。外国語(ギリシャ語か日本語のような)のテキストをこのボックスにコピーして、どのように表示されるかを 見ることができます。

これは、その編集ボックスがUTF-8の文字を返すことを確かめるのにいいテストです。 そして、そのパラグラフはどんなUTF-8の文字でも設定することができます。

重要事項:もしいくつかのUTF-8の文字が表示されないなら、パラグラフのフォントを変更する必要があります。 これは特にOS Xで一般的です。

そして、OS Xでのおすすめの日本語フォントはAppleGothicです。WindowsではMS UI Gothicです。

 Shoes.app do
   para "てすと (te-su-to)",
    font: case RUBY_PLATFORM
    when /mingw/; "MS UI Gothic"
    when /darwin/; "AppleGothic, Arial"
    else "Arial"
    end
 end

さらに、Green Shoesで文字列を扱う場合もUTF-8の文字列を必要とします。 編集ボックス、編集ライン、リストボックス、ウィンドウタイトルやテキストブロックはすべてUTF-8をとります。 間違った文字の入った文字列をあたえた場合は、コンソールにエラーが表示されます。

メインアプリケーションとRequire

注意: このルールはRaisinsのためのものです。PolicemanとGreen ShoesではTOPLEVEL_BINDINGを 使っているので、最初の例では main (Rubyトップレベルオブジェクト)が表示されます。 Shoes.appブロックの外側では、ParaではなくShoes::Paraと記述する必要がありますが。

それぞれのShoesアプリケーションは、それ自体を作ることができる小さな部屋を与えられます。 クラスを作成したり変数を設定できますが、それらは他のShoesプログラムから見ることはできません。 それぞれのプログラムはそれ自身の匿名クラス内で実行されます。

 main = self
 Shoes.app do
   para main.to_s
 end

この匿名クラスは(shoes)と呼ばれ、それは空の無名クラスです。Shoesモジュールは (include Shoesを利用して)このクラスにミックスインされているため、パラグラフクラスを参照しているときに ParaShoes::Paraを利用することができます。

このアプローチの長所は:

二つ目の部分は特に重要なので忘れないこと。

 class Storage; end
 Shoes.app do
   para Storage.new
 end

アプリケーションが完了すればStorageクラスは消えます。ほかのアプリケーションはStorageクラスを 利用できません。そして、それはrequireを利用してロードされるファイルから手に入れることはできません。

もっとも、requireするときそのコードは近くにいます。それはRubyのトップレベル環境に保持されます。

そして、この規則は:アプリケーションのコードに一時的なクラスを保持し、requireに永続的なクラスを 保持しなさいです。

Next: Shoes