現在のTinyViewは、表示している画像のサイズに合わせて、ウィンドウのサイズを自動的に調節したりしません。これではMacのアプリとは言えないでしょう。今回は、この辺りに手を入れて行きます。
まずは、zoomボタンを押した時に画像サイズを無視して画面一杯に広がってしまうのをなんとかしましょう。NSWindowクラスのリファレンスを見て下さい。setMaxSize:というメソッドがあると思います。これを使ってWindowの最大サイズを設定できます。なんだ簡単ですね。それではさっそくWindowの最大サイズを設定しましょう。設定するのはウィンドウを開く前に行わなければなりませんから、MyDocument.mのwindowControllerDidLoadNib:で設定します。それではさっそくWindowの最大サイズを・・・、最大サイズを・・・、最大サイズの値は一体いくつなのでしょう?MyImageViewのサイズで良いのでしょうか。NSScrollViewにはスクロールバーが付いてますし、縁もありますから、この分を加えなければなりません。さらにWindowにはタイトルバーも付いていますから、この分の加算も必要です。ところが、この辺りの値は固定ではありません。nibファイルで属性を変えれば変わってしまいますし、将来OSのバージョンが上がった時に、同じになるという保証もありません(多分、同じにするとは思いますけどね)。なるべくなら、値を決め打ちしないで組みたいものです。
それでは、まずはNSScrollViewから片付けて行きましょう。NSScrollViewクラスのリファレンスを見て下さい。実はNSScrollViewクラスには、スクロールバー等を加えたサイズを計算してくれる、便利なクラスメソッドが用意されています。frameSizeForContentSize:hasHorizontalScroller:hasVerticalScroller:borderType:を見て下さい。引数として中身のサイズ、水平方向のスクロールバーの有無、垂直方向のスクロールバーの有無、縁のタイプ、以上を渡すと、NSScrollViewのサイズを見積もってくれます。
それでは実装して行きましょう。スクロールバーに関する値は、NSScrollViewクラスのインスタンスから、直接教えてもらえば良いでしょう。教えてもらうためには、インスタンスの所在が分かっていないとできません。そこで、imageViewの時と同じ手法で、nibファイルをロードした時に、NSScrollViewクラスのインスタンスへのポインタをインスタンス変数にセットしてもらうことにします。この辺りの説明は既に第9回で行っていますので、詳しい解説はそちらを読んでもらうこととし、簡単に手順だけを説明します。MyDocument.hを開いて下さい。そして、次の様にインスタンス変数scrollViewを加えて下さい。加えたら、忘れずに保存して下さい。
@interface MyDocument : NSDocument { IBOutlet id imageView; IBOutlet id scrollView; NSImage *image; } @end
次にMyDocument.nibをダブルクリックしてInterface Builderで開いて下さい。開いたらnibファイルウィンドウでFile's Ownerを選び、その後Classesタブを選んでクラスの表示に切り替えて下さい(fig.01)。
[fig.01] File's Ownerを選んでからClassesタブを選ぶ |
この様に操作すると、最初からMyDocumentクラスが選ばれていますので、ClassesメニューからRead MyDocument.hを選んで、変更したMyDocument.hをnibファイルに反映させて下さい(fig.02)。
[fig.02] Read MyDocument.hを選ぶ |
反映させたら、Instancesタブを選んでインスタンス一覧に戻し、File's OwnerからNSScrollViewクラスのインスタンスにマウスをドラッグし、infoウィンドウでscrollViewを選んでConnectボタンを押して接続して下さい(fig.03)。
[fig.03] インスタンス変数scrollViewとNSScrollViewクラスのインスタンスを接続する |
以上でnibファイルの設定は終わりですので、再びXcode(もしくはProject Builder)に戻ります。
それではscrollViewのサイズを見積もるコードを書いてみましょう。
theScrollViewSize = [ NSScrollView frameSizeForContentSize:[ imageView frame].size hasHorizontalScroller:[ scrollView hasHorizontalScroller] hasVerticalScroller:[ scrollView hasVerticalScroller] borderType:[ scrollView borderType] ];
最初の引数、中身のサイズは、imageViewのサイズをセットします。
[ imageView frame].size
残念ながらimageViewには直接サイズを問い合わせるメソッドがありませんので、まずはframeを問い合わせ、その結果からsizeを取り出しています。frameは次の様に宣言されている構造体です。
typedef struct _NSRect { NSPoint origin; NSSize size; } NSRect;
つまり、sizeの取り出しは通常のC言語の構造体のメンバに対するアクセスで行っています。その他の引数は、全てscrollViewに問い合わせて状態を教えてもらい、その値をセットしています。
[ scrollView hasHorizontalScroller] [ scrollView hasVerticalScroller] [ scrollView borderType]
これでscrollViewのサイズは見積もれるようになりました。この続きは次回です。