vieweditattachhistorytopchangessearchhelp

第70回


■SqueakではじめるSmalltalk入門   第70回  鷲見 正人


本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。前回は、作成中のGUIビルダウインドウのウインドウメニューにダミーのメニュー項目を追加し、それらが機能するかどうかを確認しました。今回は、このメニュー項目を、当初の目的に沿った、ウィジェット追加のためのメニュー項目に置き換える作業をします。

ダミーのメニュー項目を、ウインドウメニューに追加するために書き足されたコードは、次のようなものでした。

aMenu add: 'inspect model' target: self action: #inspect.
aMenu add: 'inspect window' target: aMenu defaultTarget action: #inspect.


この場合、「ターゲット」として、前者にはモデル自身(self)、後者にはGUIビルダウインドウ(たまたま、項目を追加しようとしているメニューの、省略時ターゲットに指定されている…)に対して、メニュー項目選択時にinspectというメッセージを送り、それぞれのインスペクタを起動するためのアクション(実体はセレクタである#inspect)がパラメータとして添えられています。

つまり、ダミーにおいて「インスペクタを開く」ためのアクションである#inspectを、「ウィジェットを追加する」ためのしかるべきアクション(たとえば仮に#addFieldとでもしておきましょうか…)に差し替えれば、今回の目標は容易に達成できそうです。

addModelItemsToWindowMenu: aMenu
 aMenu addLine.
 aMenu
   add: 'add field'
   target: self
   action: #addField


あとは、このメニュー項目選択時に起動される#addFieldを定義するだけ…のはずなのですが、いざ、振る舞いを記述しようとするとちょっと困ったことが起こります。一般に、モデルはウインドウのことを知らない、つまり、GUIビルダウインドウを参照する手段がないため、それにウィジェットを新たに追加する手続きを記述することができないのです。

ただ、幸い、メソッド#addModelItemsToWindowMenu:内は例外で、パラメータとして与えられているメニュー(aMenu)のデフォルトターゲット(aMenudefaultTarget)として、間接的にGUIビルダウインドウのことを知ることができます。そこで、問題の解決をはかるために、ウィジェットを追加するためのメソッドを起動する際に、パラメータとしてGUIビルダウインドを受け渡すことができるよう、次のような工夫を施すことにいたしましょう。

addModelItemsToWindowMenu: aMenu
 aMenu addLine.
 aMenu
   add: 'add field'
   target: self
   selector: #addFieldTo:
   argument: aMenu defaultTarget


メニュー項目の追加用メソッドには、パラメータ無しの#add:target:action:の代わりに、パラメータを添えることができる#add:target:selector:argument:に差し替えます。アクションも、パラメータ無し(つまりコロンで終わらない)#addFieldから、パラメータを添えることができる(コロンで終わる)#addFieldTo:に改めます。

こうしておくことで、メニュー項目選択時にターゲットであるselfに対しては「addField」の代わりに、「addFieldTo: aMenu defaultTarget」というメッセージが送られることになり、#addFieldTo:内でも無事、GUIビルダウインドウを参照できるようになります。やや、バッドノウハウっぽい“香り”もしますが、必要だがselfが知りえない情報(オブジェクト)をパラメータとして受け渡してあげる方法も、この種の問題を解決する常套策のひとつとして覚えておくことも、悪くはないでしょう。

以上で「add field」というメニュー項目が追加されます。しかし、まだ、選択してもエラーになります。モデル(a GuiBuilder)が#addFieldTo:を起動できないからです。当然ですね。

#addFieldTo:の定義は、今回はとりあえず、次のようなものにしておきます。簡単のため、追加されるフィールドの大きさや位置は、ウインドウ中央に固定にしてあります。#addModelItemsToWindowMenu:を全選択して削除(cmd + A、delete)した後、下の内容をタイプして入力するか、ここからコピー&ペーストしてaccept(cmd + S)すれば、#addFieldTo:として追加されます(#addModelItemsToWindowMenu:に対する置き換えにはならないので大丈夫で
す)。

addFieldTo: window
 | field |
 field := PluggableTextMorph
   on: self text: nil accept: nil readSelection: nil menu: nil.
 window addMorph: field frame: (0.5 @ 0.5 extent: 0.5 @ 0.5)


accept後には、メニュー項目「add field」は記述どおりの動作をしてくれるはずです。次回は、ウィジェットの位置と大きさを任意に指定できるよう、この#addFieldTo:に手を加えます。

このページを編集 (3989 bytes)


Congratulations! 以下の 1 ページから参照されています。

This page has been visited 336 times.