ページ

2009年8月1日土曜日

WPSU(6) - ウィンドウを2つ重ねる(解説)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

前回のコードの解説。

まず WebViewを載せる前面のウィンドウのクラスを定義する。WebWindowと名付けた。

WebWindow.h

@interface WebWindow : NSWindow {
}
@end


実装は初期化コードおよび key window になるための -[canBecomeKeyWindow] の実装。

WebWindow.m
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithContentRect:frame
styleMask:NSUtilityWindowMask
backing:NSBackingStoreBuffered
defer:NO];

if (self) {
[self setDisplaysWhenScreenProfileChanges:YES];
[self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
}
return self;
}

- (BOOL)canBecomeKeyWindow
{
return YES;
}



Interface Builder ではベースとなる後ろのウィンドウだけを定義しておく。ここに戻るや進むのボタン、URLテキストフィールドなどを配置しておく。また WebWindowを配置するエリアを表すためにカスタムビューを配置しておく。あらかじめ Interface Builder で位置や大きさを設定しておくと、実行時に WebWindowの大きさや位置を簡単に決める事ができる。



WebViewは前面の WebWindowに載せるのでここには追加しない。ただアウトレットやアクションを Interface Builderで設定できると便利なのでインスタンス化だけしておく。


これらを使って必要な配線を済ませておく。



2つのウィンドウと WebView を統合する役割を担うのが WebController。ここで行う処理は:

・2つのウィンドウの結びつけ
・WebWindowへ WebViewを貼付ける
・NSProgressIndicatorの処理

NSProgressIndicatorは以前説明したので省略。

まずヘッダ。必要なインスタンス変数が定義されている。ほとんどがアウトレットで先ほどの InterfaceBuilderによる配線で準備される。
WebController.h
@class WebWindow;
@interface WebController : NSObject {

IBOutlet NSProgressIndicator* _progress_indicator;
IBOutlet WebView* _web_view;
IBOutlet NSWindow* _main_window;
IBOutlet NSView* _background_view;
WebWindow* _web_window;
}

@end



次に実装。Nib読み込み後に初期化する。

WebController.m
- (void)awakeFromNib
{
:
_web_window = [[WebWindow alloc] initWithFrame:[self webWindowFrame]];
[_web_window makeKeyAndOrderFront:nil];

[_web_window setContentView:_web_view];

[_main_window addChildWindow:_web_window ordered:NSWindowAbove];
:
}


まず WebWindowを生成する。続いて WebViewをコンテンツビューとして張りつける。
そして最後に -[NSWindow addChildWindow:ordered:] を使って2つのウィンドウを紐づける。紐付けによってベースのウィンドウの移動に合わせて WebWindowも位置関係を保ったまま移動するようになる。


WebWindowの位置と大きさは用意しておいたカスタムビューから取得する。
- (NSRect)webWindowFrame
{
NSRect frame = [_background_view frame];
frame.origin = [_main_window convertBaseToScreen:frame.origin];
return frame;
}

カスタムビューから得られる座標系は、そのビューが置かれているウィンドウ内のものになる。WebWindowはスクリーン座標系を使うので - [NSWindow convertBaseScreen:] で座標変換してやる。


最後にデリゲートを使ってベースのウィンドウのサイズが変わった時に WebWindowの大きさも変わる様にしておく。
// Main Window Delegate
- (void)windowDidResize:(NSNotification *)notification
{
[_web_window setFrame:[self webWindowFrame] display:YES];

}




これで2つのウィンドウがあたかも1つのウィンドウのように振る舞うようになる。



(おわり)