ページ

2008年12月21日日曜日

SimpleViewer(その2)表示位置とサイズ決め

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

表示位置とサイズを決める。順序としては、(1)画像の大きさに合わせてサイズを決め、(2)サイズを元に表示位置を決める、といった流れになる。

(1) サイズ決め
まずサイズから。パネルの大きさは画像の表示サイズによって決まるので、画像のサイズについて考える。

キャプチャ画像は大きさが様々なため、大きくて画面に収まらないケースなどが考えられるためルールを決める必要がある。以下、ルールを考えてみた。

 a. 最小サイズを設ける。QuickLookパネルを参考に、最小画像表示サイズは 320 x180ピクセルとする
 b. 初期表示のみ最大サイズを設ける。最大サイズに収まらない場合は縮小する。スクリーンサイズの 80%としよう。
 c. 最小と最大サイズに収まる場合は、画像を原寸大で表示する。

(2) 位置決め
サイズが決まったら、それを元にスクリーンの中央位置に表示されるように調整する。


制約適用のトリガーは2つある。(1)aを適用するタイミングは画像の初期表示。このタイミングでサイズを決定する情報は、画像サイズになる。(1)bを適用するタイミングは NSPanelのリサイズ時。サイズを決定する情報は(ユーザがドラッグして決める)パネルのサイズ。それぞれ決定情報が異なる。

 (1)a サイズ決定要素:画像サイズ  タイミング:画像表示時
 (2)b サイズ決定要素:パネルサイズ タイミング:リサイズ時


(1)a を実現するには NSPanelのリサイズを制御する。delegateメソッド NSWindow#windowWillResize:toSize: を使う。

- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize
{
NSRect rect = [sender frame];
rect.size = frameSize;
rect = [sender contentRectForFrameRect:rect];
rect.size.height -= BUTTON_BAR_HEIGHT;
rect.size = [self adjustContentSize:rect.size];
rect.size.height += BUTTON_BAR_HEIGHT;
rect = [sender frameRectForContentRect:rect];

return rect.size;
}

リサイズ時にこのメソッドがコールバックされる。渡されたサイズが最小サイズを下回る場合は調整して( #adjustContentSize:)戻りちとして返す。BUTTON_BAR_HEIGHTは下部にあるボタンの高さ。NSPanelと内部のコンテントビューの大きさは NSWindow#contentRectForFrameRect:rect: と NSWindow#frameRectForContentRect:rect でそれぞれ変換ができる。

(1)b は、画像を初期表示する時に調整する。
 NSSize max_size = [self maximumContentSize];

CGFloat ratio_w = max_size.width / content_size.width;
CGFloat ratio_h = max_size.height / content_size.height;
if (ratio_w < 1.0 || ratio_h < 1.0) {
CGFloat ratio = fminf(ratio_w, ratio_h);
content_size.width *= ratio;
content_size.height *= ratio;
}

幅と高さでより小さくなる方の比率を採用してサイズを作る。こうしないとNSimageViewで表示した時、左右(もしくは上下)に余白ができてしまう。


サイズが決まったら、最後に位置合わせ。スクリーンのサイズを取得すれば位置は簡単に決められる。
 NSRect screen_frame = [[NSScreen mainScreen] visibleFrame];
NSRect panel_frame = [_viewer_panel frame];
NSPoint panel_origin;
panel_origin.x = (screen_frame.size.width - panel_frame.size.width) / 2.0;
panel_origin.y = (screen_frame.size.height - panel_frame.size.height) / 2.0;
panel_origin.y += screen_frame.origin.y; // for Dock Height
[_viewer_panel setFrameOrigin:panel_origin];

Dock の高さを補正してある。これは NSScreen#visibleFrameの origin.y が相当する。



いい感じだ。