ページ

2010年4月10日土曜日

NSWindow カスケード、カスケード

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

一般的な Cocoaを使った Document-Viewアーキテクチャのアプリでは新規にウィンドウを開くとカスケード表示になる。テキストエディット.app の例。

NSDocumentController などを使うと新規ウィンドウ表示時の位置は自動的にカスケード表示となる。これを自前でやるにはどうしたらいいか?


NSWindowにはカスケード用のメソッドが用意されていて、これを使うと簡単にできる。


NSWindow Class Reference - cascadeTopLeftFromPoint:

このメソッドは引数に渡された座標を基準に、次に(カスケードで)表示すべき座標を返してくれる。新規のウィンドウをカスケード表示したい場合は、現在のウィンドウ位置を引数へ渡し、戻り値を使う。

サンプルを作ってみた(GitHub)
CascadingWindows at 2010-04-10 from xcatsan's SampleCode - GitHub

コードはこんな感じ。

@implementation CascadingWindowsAppDelegate

@synthesize window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application 
nextTopLeft = [window cascadeTopLeftFromPoint:NSZeroPoint];
}


- (IBAction)createWindow:(id)sender
{
NSRect rect = NSMakeRect(0, 0, 320, 200);
NSWindow* w = [[NSWindow alloc]
  initWithContentRect:rect
  styleMask:NSTitledWindowMask
  backing:NSBackingStoreBuffered
  defer:NO];
nextTopLeft = [w cascadeTopLeftFromPoint:nextTopLeft];
[w setTitle:NSStringFromPoint(nextTopLeft)];
[w  makeKeyAndOrderFront:nil];
}

@end


サンプルではメニューの File > New を上記の createWindow: へ紐付けて、新規ウィンドウを作る用にしている。この時に cascadeTopLeftFromPoint: を使って位置決めする。なおこのメソッドを使うとレシーバのウィンドウの表示位置が引数の座標になる。

こんな感じ。NSZeroPoint を最初の点とするとメニュー下の左上角に最初のウィンドウが現れる。


なおウィンドウが下まで行くとどうなるか。その場合もちゃんと考えられていてウィンドウが隠れそうになったら右上から再びカスケード表示になる。



さらに右の方までウィンドウを開くとどうなるのか?この場合は画面左上に基点が戻る。

その際の基点は、一番最初めの基点から少し下の方となる。

芸がこまかい。