ページ

2008年2月24日日曜日

スクラップブックその12 - 画像の拡大縮小

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

画像を拡大縮小できるようにしてみる。



ソースコード:sp4-12.zip


拡大縮小はよくある四方に□をつけて行うやつではなく、ウィンドウのように右下だけで行うようにする。
<=このアイコンを画像の右下に表示する。この画像は OSについていた resize.gifを拝借している。

リサイズアイコンは画像が選択された時だけ表示して機能するようにする。こんな感じ。




機能実装のポイントは次のとおり。
 (1) リサイズアイコンの表示
 (2) リサイズアイコンドラッグ時の処理(拡大縮小)


(1) リサイズアイコンの表示
以前、導入した ItemIcon クラスを改良して使うことにする。初期化時に画像の4角(左上、右上、左下、右下)のどこへ表示するか指定し、位置決めの為に以前の setOrigin: をやめて、紐づける画像のサイズを渡す setBaseRect: に変更した。
その後、WorkViewに新たに ItemIconのインスタンス変数を追加し、表示処理を加えた。

(2) リサイズアイコンドラッグ時の処理(拡大縮小)
mouseDown: の中でリサイズアイコンのヒットテストを行い、押されているようなら新設のメソッド resizeIcon: を呼ぶ。

WorkView.m

-(void)resizeItem:(Item *)item
{
NSPoint current_point;
NSEvent* theEvent;

while (1) {
theEvent = [[self window] nextEventMatchingMask:(NSLeftMouseDraggedMask | NSLeftMouseUpMask)];
current_point = [self convertPoint:[theEvent locationInWindow]
fromView:nil];

[self autoscroll:theEvent];

[item setSize:NSMakeSize(current_point.x - [item.x floatValue],
current_point.y - [item.y floatValue])];
[_icon setBaseRect:[item rect]];
[_resize_icon setBaseRect:[item rect]];
[self setNeedsDisplay:YES];
if ([theEvent type] == NSLeftMouseUp) {
break;
}
}
}


ここでイベントループを作り、マウスボタンが離されるまで画像サイズの拡大縮小計算を行う。ドラッグの時にやっていた移動量のチェックは今回は行っていない。

画像をビューへ描画するのに以前 compositeToPoint:operation: を使っていたが、これでは拡大縮小表示ができないので別のメソッド NSView#drawInRect:fromRect:operation:fraction: を使う。

fromRect: に NSZeroRectを指定すると画像のサイズが使われ、これが drawInRect: で指定した領域へ写像される(拡大縮小が行われる)。



忘れずに dragImage: に渡す画像作成も compsiteToPoint: から drawInRect: へ切り替えておく。


なお compsiteToPoint: を drawInRect: へ切り替えただけだと画像が上下反転して表示されてしまう。



これは drawInRect: の場合はビューの flip状態を見て描画する為。スクラップブックでは描画先のビューである WorkView の isFlipped で YESを返すようにしている。この為、drawInRect: を使うと図のように上下反転してしまう。そこで画像も反転表示するように setFlipped: を使い flip属性を変えてしまう。最終的な WorkView#drawRect: は次のようになる。

- (void)drawRect:(NSRect)rect {
[[NSColor whiteColor] set];
NSRectFill(rect);

for (Item* item in [_controller items]) {
[item.image setFlipped:YES];
[item.image drawInRect:[item rect]
fromRect:NSZeroRect operation:NSCompositeSourceOver
fraction:1.0f];
[item.image setFlipped:NO];

if (_selected_item == item) {
// draw selection
[[[NSColor grayColor] colorWithAlphaComponent:0.3f] set];
[NSBezierPath fillRect:[item rect]];
[_icon draw];
[_resize_icon draw];
}
}
}


これで画像が正しく表示されるようになった。

- - - -
選択すると灰色になるがちょっと見づらい。枠に戻すか、別の表現の方がよさそう。