第65回
■
■SqueakではじめるSmalltalk入門 第65回
■
本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。今は、簡単なGUIビルダを構築することを目指して、そのために必要なテクニックや知識を整理しているところです。
前回は「fromUser」というメッセージを、座標や矩形を表現するクラスに送信することで、直後のマウス操作から情報をオブジェクトとして情報を引き出すことが可能であることを確認しました。たとえば、RectangleクラスにfromUserメッセージを送れば、「Rectangle class >> #formUser」というメソッドが起動し、直前のマウスドラッグ操作で描いた矩形の座標を得ることができます。この方法で、位置や大きさをあらかじめ指定して、新しいウィジェットを設置する操作が実現できそうです。さっそく試してみましょう。
| field |
field := PluggableTextMorph new.
field editString: ''.
field bounds: Rectangle fromUser.
field openInWorld
とりあえず、このスクリプトの全体を選択し、do it(cmd + D)で実行してみてください。マウスポインタが十字(クロスヘア)に変化するので、画面の任意の位置でドラッグして矩形を描くと、ぴったりその位置にテキスト編集用のフィールドが現れます。
[fig.A,B]Rectangle fromUserの位置にテキストフィールドを生成
念のため、スクリプトの内容を順を追って解説してみましょう。まず最初は、テンポラリ変数「field」の宣言文。続けて、PluggableTextMorphのインスタンス(a PluggableTextMorph)を作り、その変数「field」に束縛しています。
fieldに束縛されたa PluggableTextMorphの初期化のために、メッセージ「editString: ''」を送った後、くだんのRectangle fromUserを使って得た矩形情報(a Rectangle)をパラメータに添えて、#bounds:というメソッドを起動しています。この#bounds:メソッドはMorphに定義されていて、モーフの位置と大きさを一発で決めることができます。つまり、
| morph |
morph := Morph new.
morph bounds: (100@100 extent: 100@100).
morph openInWorld
は、
| morph |
morph := Morph new.
morph position: 100@100.
morph extent: 100@100.
morph openInWorld
と同じことをします。
位置と大きさを決められたa PluggableTextMorphは、最後にopenInWorldメッセージを受け取って、我々の前にその姿を現わします。ただ、実際のシステムウインドウに埋め込む作業には、#add:frame:を起動するだけでよいので、#bounds:以下は、軽く流していただいて結構です。
さて、このように単に作られただけのテキストフィールド(aPluggableTextMorph)は、テキストの入力などの基本的な機能こそ正常ですが、モデルに依存する黄ボタンメニューを出すことができません。第62回のときは“魂”を欠いた状態などと抽象的に表現していましたが、実装的には、どんなことが起こっているのかを探ってみることにします。
とりあえずは、黄ボタンメニューを出すことだけを考えてみます。まず手始めに、手本となったワークスペースでテキストフィールドを作っているときのメッセージをそのまま真似てみることにしましょう。
PluggableTextMorphを選択して、cmd + shift + Nとタイプすると、そのクラスを含むメソッドの一覧をブラウズできるので、その中から、StringHolder >#openAsMorphLabel:inWorld:というメソッドを探して定義を見ると、次のようなワークスペースのウインドウを構築する記述が見つかります(改行の位置はわかりやすいように変えました)。
window
addMorph: (
PluggableTextMorph
on: self
text: #contents
accept: #acceptContents:
readSelection: nil
menu: #codePaneMenu:shifted:)
frame: (0@0 corner: 1@1).
ここで、#on:text:accept:readSelection:menu:を起動する際に添えられているパラメータを、そのまま真似ればよいのですが、他のパラメータと違い、第一パラメータのselfだけは文脈に依存する擬変数なので、別のものに置き換えなければいけません。
ワークスペースが作られるときの文脈では、このメソッド(StringHolder >> #openAsMorphLabel:inWorld:)を起動したワークスペースのインスタンス(aWorkspace)がselfに束縛されていることになりますから、このことを考慮して、冒頭のスクリプトを書き換えると次のようになります。
| field |
field := PluggableTextMorph
on: Workspace new
text: #contents
accept: #acceptContents:
readSelection: nil
menu: #codePaneMenu:shifted:.
field bounds: Rectangle fromUser.
field openInWorld
改めてスクリプト全体を選択してdo it(cmd + D)すると、今度のテキストフィールドは、黄ボタンメニューも使えるようになっていることが確認できるはずです。
[fig.C]黄ボタンメニューをポップアップさせたところ
じつは、セレクタのキーワードから想像できるように、黄ボタンメニューを出すだけなら、最初と最後のパラメータだけをきちんと渡せば、あとはnilでも目的を果たすことができます。
| field |
field := PluggableTextMorph
on: Workspace new
text: nil
accept: nil
readSelection: nil
menu: #codePaneMenu:shifted:.
field bounds: Rectangle fromUser.
field openInWorld
このことを手がかりに、次回、黄ボタンメニューがどのように呼び出されているのかを、もう少し掘り下げて調べてみることにします。
このページを編集 (4716 bytes)
|
以下の 1 ページから参照されています。 |
This page has been visited 792 times.