![]() |
[1999 年 7 月号] |
[Happy Squeaking!!]
それでは3つ組の最後としてビューを作成することにしましょう。
まずは抽象クラスViewのクラス定義をみてみます。
View definition. "print it"
Object subclass: #View instanceVariableNames: 'model controller superView subViews transformation viewport window displayTransformation insetDisplayBox borderWidth borderColor insideColor boundingBox ' classVariableNames: '' poolDictionaries: '' category: 'Interface-Framework'
伝統的なMVCの場合、Viewの役割はかなり広範です。ここでもすべてを把握する必要はありません。重要なのはmodel、controllerの各属性です。model変数によるモデルへの参照は、モデル更新時に最新の値を取得するために使われ、controller変数によるコントローラの参照は、ウィンドウビューがリストビューを含んでいるなど、ビューが入れ子関係になっている時に、子供のビューのコントローラに制御権を渡す場合などに役立ちます。(Viewの入れ子については今回のサンプルでは取り扱いません)。
Counter用のビューですが、ウィンドウとして表示されるようにしたいので、例によってViewそのものではなく、そのための機能が実装されたStandardSystemViewのサブクラスとして作成します。
表示の仕方についてはいろいろ考えられますが、ここではやはりシンプルに、テキスト形式で現在のモデルの値が表示されるのみとします。
クラス定義は次のようになります。
StandardSystemView subclass: #CounterTextView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'MVC tutorial'
カウンタの値についての情報はCounterモデルで管理されているので、View側では一切Counterの値について情報をもつ必要がありません。結果としてCounterTextViewは属性なしのクラス定義となっています。
ビューで行うことは何といっても"表示"ですから、そのための操作を定義します。
(CounterTextView >> displayingカテゴリ)
displayView | countStr text displayText | super displayView. self clearInside. countStr := self model data printString. text := Text string: countStr attribute: (TextEmphasis bold). displayText := text asDisplayText. displayText foregroundColor: Color black backgroundColor: Color white. displayText displayAt: self insetDisplayBox center
といった具合になります。
幾つか新しい事項が出てきています。順番に説明します。
まずdisplayViewですが、ビューの再描画が必要になった時に自動的に起動されます。デフォルトでは、モデルの状態とは無関係に、ウィンドウのリサイズや移動を行った際に呼ばれるようになっています。
新たなビューを定義した場合には、最低でもこのメソッドを実装しないと適切な表示を行わせることができません。
displayViewの中身ですが、コメントつきで示すと以下のようになります。
displayView | countStr text displayText | "デフォルトの再表示処理を実行" super displayView. "ビュー内部の表示をリフレッシュする" self clearInside. "モデルから、Counterの値を文字列形式で取得" countStr := self model data printString. "ボールド体のテキストを生成する" text := Text string: countStr attribute: (TextEmphasis bold). "テキストを表示テキストに変換" displayText := text asDisplayText. "表示テキストに色をつける" displayText foregroundColor: Color black backgroundColor: Color white. "ビュー内部の中心部に表示テキストの描画" displayText displayAt: self insetDisplayBox center
説明が特に必要なのはTextと思います。
TextはStringと違い、単なる文字列でなく、ボールドである、イタリックであるなどの属性を持つ文字列です。Textはそのままではビットマップ表示を行うことができず、Textを一旦DisplayTextに変換しなければなりません。DisplayTextはDisplayObjectのサブクラスで、displayAt:
やdisplayOn: at: を使うことでビットマップディスプレイに表示を行わせることができます。
コード例を示すと以下のようになります。
| text disText | "イタリックのテキスト属性を生成" att := TextEmphasis italic. "イタリック属性の設定されたテキストを生成する" text := Text string: 'HelloSqueak' attribute: att. "DisplayTextのインスタンスへと変換" disText := text asDisplayText. "現在のカーソル位置に表示" disText displayOn: Display at: Sensor cursorPoint
Displayは、Squeakビットマップ画面の全体を指すグローバルなオブジェクトです。Sensorも、Squeak全体に関するグローバルなセンサです。
さらに興味のある方は Text、TextEmphasis、DisplayObject、DisplayTextの各クラスをブラウズしてみてください。 |
SmallTip:Textは、ボールド、イタリックなどの属性をもつ文字列 |
SmallTip: DisplayObjectは、displayAt: によって表示を行わせることができる |
次に、モデルからデータの更新があったときに呼ばれるupdate: メソッドを定義します。これは、Counterの値の変更があった段階でSqueakのdependency機構の働きによって自動的に起動されます。
モデルからの通知があった際に、ビューはアップデートを行うべきなので、以下のように定義します。
(CounterTextView >> updatingカテゴリ)
update: anAspect Transcript cr; show: 'now update'. "先に定義したdisplayViewを呼び出す" self displayView.
引数anAspectはとりあえず無視してください。ビューのupdateをより細かい単位で行う際に使用されます。
最後に、このビューがデフォルトで使うコントローラを示すためのメソッドを定義します。CounterTextViewは、先ほど作成したCounterKeyboardControllerと協調して動作しますので、以下のようなメソッドを作成することになります。ビューは、外部からコントローラが設定されていない場合、このメソッドを呼び出して自身が使うコントローラとします。
(CounterTextView >> controller accessカテゴリ)
defaultControllerClass ^CounterKeyboardController
これでビューの作成も終わりました。
以下は全体のソースです。
FileIn: CounterTextView.st (<=Click)
© 1999-2001 OGIS-RI Co., Ltd. |
|