タイトル今から始めるCocoaプログラミング》文書ファイルを扱うアプリケーションを作る(8)新規にウインドウを開くときの処理カテゴリーユーザインタフェース, Cocoa, 今から始めるCocoaプログラミング
作成日2001/12/27 14:55:50作成者新居雅行
前回の説明で忘れ物があった。文書ファイルに対応したnibファイルのMyDocument.nibファイルに、Windowというインスタンスがあり、そこにNSTextViewを配置したが、その属性を一部変更しておいてもらいたい。

◇NSTextViewのAttributesを変更する
 

Windowsの中にあるNSTextViewを選択すると、InfoパレットにNSTextViewの設定が表示される。Attributesをポップアップメニューから選択し、設定を行う。ここでGraphics allowedとUndo allowedのボックスがオフになっているがそれを入れておく。いずれにしても、テキスト編集領域の設定をここで行えるが、属性についてはもちろん、プログラムで変更ができる。
Editableはもちろん、編集作業が可能かどうかで、たとえばテキストの表示だけを行うのなら、このチェックははずせばいいだろう。もし、このチェックをはずせばSelectableが選択できるようになり、編集はできないが選択してコピーなどの作業ができるようになる。Multiple fonts allowedは文字単位でフォント設定を変化させるような書式設定を可能とするかどうかだ。Graphics allowedは、インライングラフィックスの挿入を可能するかどうかを示す。Undo allowedはUndoが可能かどうかだが、実はRevertメニューが使えるかどうもここのチェックに関係しているようである。

続いてプログラムに移りたいが、今のところはまだ、1行だけしか追加していないMyDocument.javaを見て見よう。すでにいくつかのメソッドが定義されている。

◇MyDocument.javaの最初の状態
 

ここで改めて、ドキュメントベースのアプリケーションで稼働しているオブジェクト階層を見ながら解説をしよう。以前にも示したが、以下の図だ。

◇ドキュメントベースのアプリケーション
 

ここで、ドキュメントを管理するNSDocmentのサブクラスとして、MyDocomentクラスが定義されている。NSDocumentのサブクラスは必ず作らないといけないと説明したが、そのサブクラスで必ずオーバーライドしなければないメソッドがある。それぞれ、各メソッドで組み込まないといけない機能は以下の通りだ。

☆ウインドウに表示されている文書データを、ファイルに保存できる形式に整える(Override)
 NSData dataRepresentationOfType(String aType);
 戻り値:文書データをNSData型にしたもの。nullを戻すと保存のキャンセル
 引数:aType:保存する文書の型を示す文字列(書類タイプの「名前」)

☆文書ファイルから読み取ったデータをどこかに保存しておく(Override)
 boolean loadDataRepresentation( NSData docData, String docType);
 戻り値:読み込み動作をキャンセルするなfalse、続けるならtrueを戻す
 引数:docData:ファイルから読み取ったデータが得られる
    aType:ファイルの文書の型を示す文字列(書類タイプの「名前」)

☆このクラスに関連付けられているnibファイルの名前を戻す(Override)
 String windowNibName()
 戻り値:nibファイルのファイル名(拡張子は不要)

◇NSDocument(com.apple.cocoa.application)
 http://devworld.apple.com/techpubs/macosx/Cocoa/Reference/ApplicationKit/Java/Classes/NSDocument.html

これらのメソッドを定義しないといけないのであるが、すでにテンプレートの状態でメソッドの外枠は作られている。(NSDataについてはこの記事の末尾に解説する。)後は中身を書くだけということになっている。

それぞれのプログラムを示す前に、すでに何もプログラミングをしなくても動いている部分を見て見たい。アプリケーションを起動したり、あるいはFileメニューからNewを選択すると、新たに文書ウインドウが作られる。まだ、文書ファイルとの対応は取られていないが、とにかく設計したユーザインタフェースのウインドウがでてくるのである。ここでは、次のような流れがフレームワーク内で発生している。

(1)起動やメニュー操作によって新しいドキュメントを作るというイベントが発生する。
(2)First Responderによって受け取られる。結果的にそれがNSDocumentControllerで受け取られて処理が行われる。
(3)アプリケーション情報をもとに一連のドキュメント対応オブジェクトを構築する。まず、「書類のタイプ」の設定の最初の項目から、文書ファイルはMyDocumentクラスで管理することが分かる。(複数ある場合は最初の項目を取り出す)
(4)MyDocumentの引数のないコンストラクタが呼び出されて、MyDocumentオブジェクトが生成される。
(5)MyDocumentのwindowNibNameメソッドが呼び出される。これによって、NSDocumentControllerがロードすべきnibファイルを知ることができる。そして、ここではwindowNibNameで得られた名前をもとに、MyDocument.nibファイルがロードされる。
(6)MyDocument.nibの定義に従ってウインドウが表示され、そこに定義したユーザインタフェースなどが定義通りに画面に表示される。
(7)nibファイルをロード後にMyDocumentのwindowControllerDidLoadNibメソッドが呼び出される。

最初でのFirst Responderについては別途説明するが、簡単に言えば、さまざまなイベントの流れを一元的に受け付けるオブジェクトだと考えれば良い。そして、フレームワークの中で、そのイベントを受け付ける流れができている。たとえば、テキスト編集中はテキストフィールドが受け付けるがそこで処理されないイベントはアプリケーションなどに引き継がれるといった連鎖が自動的に内部で構築されているのである。
テンプレートからプロジェクトを作成すると、すでにいろいろなところで「MyDocument」という設定がなされているが、上記の流れをもとに、どのデータをもとにしてどのデータが取り出されるかという関連付けをチェックしておいてもらいたい。複数のドキュメントクラスやnibファイルを扱う場合にはそうした知識がないといけないだろう。

 ̄ ̄ ̄ ̄NSDataについて____
NSDocumentでのオーバーライドしなければならなかったメソッドでは、データをNSData型で取り扱わないといけない。これは、CocoaのFoundationに定義されたクラスであるが、要はバイト型データの配列を保持してパッケージとして扱うためのクラスである。以下は、コンストラクタと利用するメソッドをまとめておいた。いずれにしても、データはbyte型の配列で得られるので、byte配列のラッパークラスということである。

☆NSDataクラスのインスタンスを生成するコンストラクタ
 NSData()
 NSData( byte[] bytes, int start, int length)
 NSData(byte[] bytes)
 NSData(java.io.File aFile)
 NSData(java.net.URL anURL)
 NSData(NSData aData)
 NSData(String aString)
 戻り値:生成したNSDataオブジェクトへの参照
 引数:bytes:データが入っているbyte型配列
    start:取り出す最初の位置(ないものはbyte配列全部のNSDataを作る)
    length:取り出すバイト数(ないものはbyte配列全部のNSDataを作る)
    aFile、anURL:ファイルやURLから取り出したデータをもとにNSDataを作成
    aString:文字列をもとにしたNSDataを作成

(以下、《》はそのクラスのインスタンスへの参照を指定することを意味する。)

☆NSDataに含まれているデータの長さを求める
 int 《NSData》.length();
 戻り値:含まれているデータのバイト数

☆NSDataに含まれているデータを取り出す
 byte[] 《NSData》.bytes(int start, int length);
 戻り値:含まれているデータ
 引数:start:取り出す最初の位置
    length:取り出すバイト数

◇NSDocument(com.apple.cocoa.foundation)
 http://devworld.apple.com/techpubs/macosx/Cocoa/Reference/Foundation/Java/Classes/NSData.html

(この項、続く)
関連リンク