NSOutlineViewでのドラッグ&ドロップ

検索用にdrag and dropおよびD&D.というかドロップのみだけど.

NSTableView のように NSTableDropOn/NSTableDropAbove のような定数による区別は無いので注意.dataSourceに渡された引数で判別する必要がある.

outlineView:acceptDrop:item:childIndex:outlineView:validateDrop:proposedItem:proposedChildIndex: で渡される引数は同じっぽい(多分)ので,ここではリファレンスに従って,

- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id )info item:(id)item childIndex:(int)index

と宣言したと仮定しておく.まぁ outlineViewinfo は自明なので, 以下は itemindex の値とそのときの NSOutlineView 上での挙動について記述する.

まず item はドラッグ先の親アイテムを指している(なので個人的には parentItem とかのほうが適当な気がする).従ってもしドラッグ先が親アイテムを持たない最上位のアイテムだった場合には nil となる. そして indexitem におけるドラッグ先の子アイテムのインデックスを指す.例えばその子アイテムを取り出したければ,

id child = [item childAtIndex:index];

のようにすれば良い.

NSTableDropOn のようにドラッグ先のアイテムが太枠で囲まれているとき

item はそのドラッグ先のアイテムを指し, index は -1 が与えられる.例えば itemnilindex-1 のときには, NSOutlineView の最上位に対してアイテムを追加するような挙動が求められている.

NSTableDropAbove のようにドラッグ先のアイテムに太い下線が表示されているとき

item はドラッグ先のアイテムの親を指し, index は表示されている下線の直下にあるアイテムのインデックスを指す..このとき NSOutlineView は絵的に挿入を表しているので,

[item insertChild:theDraggedItem atIndex:index];

のようにすれば良い.もちろん itemnil のときは別に考える必要がある.また

[item count] == index

のような場合がある( index は0ベースなので, NSArray 的にはあり得ない).これは item の子アイテムの最後尾に下線がついているときに起こる.で,例えば NSMutableArray はinsertObject:atIndex: のインデックスに count よりも大きな値を渡すと例外が発生するので,代わりにaddChild: のようなことをする必要があるので注意.