ページ

2008年2月10日日曜日

スクラップブックその5 - スクロールバー追加

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

今度はスクロールバーを追加する。



Interface Builder で WorkViewを選択後、メニューから Layout->Embed Objects In->Scroll View を選ぶ。
これだけだと画像が WorkViewの範囲外にはみ出てもスクロールできない。はみ出た分だけ WorkViewの frameサイズを大きくする必要がある。

そこでドラッグ処理内で範囲外かどうかを判断して、その場合は frameサイズを拡大する処理を追加する。

WorkView.m


- (void)mouseDown:(NSEvent *)theEvent {
  :
 [self resizeWithRect:[item rect]]; // item ...ドラッグしている画像
  :
}

- (void)resizeWithRect:(NSRect)rect
{
float x = rect.origin.x + rect.size.width;
float y = rect.origin.y + rect.size.height;
NSSize view_size = [self bounds].size;
BOOL changed = NO;

if (view_size.width < x) {
view_size.width = x;
changed = YES;
}
if (view_size.height < y) {
view_size.height = y;
changed = YES;
}
if (changed) {
[self setFrameSize:view_size];
}
}


これでドラッグ中に WorkViewをはみ出すとスクロールバーが出るようになる。

なお、スクロールバー追加にあわせて WorkViewの y座標を反転(flip)させている。
WorkView.m

- (BOOL)isFlipped
{
return YES;
}


NSViewの座標系はデフォルトでは左下が (0,0)となるが、isFlippedをオーバーライドして YESを返すとそのViewは左上が (0,0)の座標系となる。
ただこのままでは画像が正しい位置に表示されないので、描画時に compositeToPoint:operation の位置を補正している。

[item.image compositeToPoint:NSMakePoint([item.x floatValue],
[item.y floatValue]+[item.height floatValue])
operation:NSCompositeSourceOver];


Flipped Coordinate Systems の Drawing Content in a Flipped Coordinate System > Drawing Images によると、compositeToPoint:fromRect:operation: を使った描画では、描画開始位置のみが isFlippedの影響を受けて、NSImage自体の座標系は変わらない(左下が (0,0)として右上方向に描画される)。このあたりの動きは「Figure 3-9 Compositing an image to a flipped view」の図を見ると一目で分かる。

NSImageの座標系も setFlipped: を使い Y座標を反転させることができるが、実際これは(感覚的に意図したようには)働かない。使って見ると下のように上下反転した表示になる。



この辺りは下記に記述がある。
Image Coordinate Systems