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つのparaは stack上に描画されます。
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を変更します。
(これは、window とdialog同様に、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を利用して)このクラスにミックスインされているため、パラグラフクラスを参照しているときに ParaやShoes::Paraを利用することができます。
このアプローチの長所は:
- Shoesアプリケーションはローカル変数を共有できません。
- メインアプリケーションコードに作成されるクラスは一時的です。
- Shoesモジュールは、Ruby自身のトップレベル環境ではなく、匿名クラスにミックスインされることができます、
- ガベージコレクションが一度完了すれば、アプリケーションを完全にきれいにできます。
二つ目の部分は特に重要なので忘れないこと。
class Storage; end
Shoes.app do
para Storage.new
end
アプリケーションが完了すればStorageクラスは消えます。ほかのアプリケーションはStorageクラスを 利用できません。そして、それはrequireを利用してロードされるファイルから手に入れることはできません。
もっとも、requireするときそのコードは近くにいます。それはRubyのトップレベル環境に保持されます。
そして、この規則は:アプリケーションのコードに一時的なクラスを保持し、requireに永続的なクラスを 保持しなさいです。
Next: Shoes