にけのて
Nike+iPod と JogNote を使ってジョギング。で、Mac から Nike+ のデータをあれこれ見たくなったので、ちょこちょこっと作ってみた。
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

NSImageView からの Action はどこから出てくるのか?
何が言いたいのかわからないタイトルだな。

NSImageView を使うと特に何もしなくてもドラッグ&ドロップを受け付けてくれる。楽チン。IBNSImageView から自前のコントローラへ Action: を繋げれば、イメージが変わったときに(ドロップされたときに)メッセージが飛んでくる。(言葉はこれで良いのかな?)
でも、 NSImageView から得られるのは NSImage。そうじゃなくてドロップされたイメージの(オリジナルの?)NSURL が欲しいんだよな~。どうにかならないのかな?

というわけで、NSImageView のサブクラス MyImageView を作ってドラッグ&ドロップをやってみた。
ドラッグ&ドロップは資料を見ればなんとかなる。面倒ではあるけど難しくはない。とりあえずは受け取る側だから registerForDraggedTypes: で受け取る Type を登録して

- (id)initWithFrame:(NSRect)frameRect
{
[super initWithFrame:frameRect];
[self setImageFrameStyle:NSImageFrameGrayBezel];
[self registerForDraggedTypes:[NSArray arrayWithObjects:NSURLPboardType, nil]];
return self;
}


後はNSDraggingDestination protocol に対応?すれば良い。全部で8つ。

Managing a Dragging Session Before an Image is Released
– draggingEntered:
– wantsPeriodicDraggingUpdates
– draggingUpdated:
– draggingEnded:
– draggingExited:
Managing a Dragging Session After an Image is Released
– prepareForDragOperation:
– performDragOperation:
– concludeDragOperation:

でも、draggingEnded: はまだないらしいので実質7つ。
で、ドラッグ&ドロップでイメージを受け取るときの流れはこんな感じ。

・イメージが MyImageView の上に入って来たら最初に draggingEntered: がくる。で、[sender draggingPasteboard] から何が来てるのかを確認して、自分が受け取れるなら Dragging operations の中から返事を返す。受け取れるなら NSDragOperationCopy で良いんじゃない? Move や Delete だとオリジナルが無くなっちゃうし。で、ここで MyImageView を暗くしたりしてドラッグ&ドロップできるよ!って表示にする。
今回は NSURL が欲しかったから、それがあるかどうかを確認してみる。

NSPasteboard *pb = [sender draggingPasteboard];
NSArray *supportedTypes = [NSArray arrayWithObjects: NSURLPboardType, nil];
NSString *bestType = [pb availableTypeFromArray:supportedTypes];
if (bestType) {
[self setImageFrameStyle:NSImageFrameGroove];
return NSDragOperationCopy;
}
else
return NSDragOperationNone;


・次にイメージが NSImageView の上にあり続ける?場合、延々と draggingUpdated: が送られてくる。その度に Dragging operations の中から返事を返す。今回は常に draggingEntered: で返した返事と同じものを返してる。場所によって処理を変えたりしたい場合はここで毎回チェックして返事を変えたりするのかな?

・もし「やっぱりや~めた」とかでイメージが MyImageView の上から外れたら、draggingExited: が送られてくる。ここで FrameRect を暗くしてたら元に戻さないと。更にその後でまた NSImageView の上に来たら、最初の draggingEntered: から始まる。

[self setImageFrameStyle:NSImageFrameGrayBezel];


・MyImageView 上でイメージがリリースされたら(ボタンがはなされたら)、直前の draggingEntered: メッセージか draggingUpdated: メッセージの返り値によってイメージが元の場所に戻るか prepareForDragOperation: メッセージがくるかのどちらかになる。自分が対応していない場合は MyImageView の見た目は変えないから、そのままイメージが戻って終わり。対応している場合は次へ行く。
用意しろって言われても、特にする事ないしな~。YES だけ返しとく。

・もし、prepareForDragOperation: メッセージで YES が返された場合は、perFormDragOperation: メッセージが来る。ここでドラッグされた側のデータのコピーやら何やらの作業をする。ここで NSURLNSPasteboard からゲットできる。

NSPasteboard *pb = [sender draggingPasteboard];
NSString *bestType = [pb availableTypeFromArray:[NSArray arrayWithObjects: NSURLPboardType, nil]];
if (bestType) {
_myURL = [[NSURL URLFromPasteboard:pb] retain];
[self setImage:[[NSImage alloc] initWithPasteboard:pb]];
return YES;
}


・最後に perFormDragOperation: メッセージが YES を返したら、concludeDragOperation: メッセージが来る。後始末とか?する。
とりあえず MyImageView の見てくれを元に戻そう。

[self setImageFrameStyle:NSImageFrameGrayBezel];


wantsPeriodicDraggingUpdates: が出てこないけど、これは draggingUpdated: が送られてくるタイミングについて YES/NO で値を返すだけ。別に何もしなくても大丈夫みたい。

というわけで、あれこれ試行錯誤しながらなんとかドラッグ&ドロップはできたのだけど、最後に Action: が送られてこない!

ということから「NSImageView からの Action はどこから出てくるのか?」というタイトルになったのだけど、どうなんだろう? MyImageView の Action: の情報をゲットして(どうやって?)、その情報から送り先と selector をゲットしてメッセージを送るって感じ? 良く解らん!

ので、結局は最後の後始末 concludeDragOperation で super さんにそのまま任せてみた。そしたら Action: が飛んでったので結果オーライということで。良いのか?そんな事で!

ん~タブって消えるんだ。リストが見難いな。サンプルのコードを適当にいぢっただけだから、かなり怪しい部分があると思うけど…
スポンサーサイト

テーマ:プログラミング - ジャンル:コンピュータ


この記事に対するコメント

この記事に対するコメントの投稿














管理者にだけ表示を許可する


この記事に対するトラックバック
トラックバックURL
→http://paraches.blog77.fc2.com/tb.php/32-6d128222
この記事にトラックバックする(FC2ブログユーザー)

プロフィール

Author:paraches
Nike+iPod で走ってお腹を…

にけのて ダウンロード

Nike+iPod

温泉旅行

宿・ホテル予約ならじゃらんnet

最近の記事

Zenback

ランキング

人気ブログランキングへ

アクセストレード

バリューコマース

最近のコメント

月別アーカイブ

RSSフィード

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。