Nakajijapan

生きるのに必死です。

自作のアプリから他のWindowに画像をドラッグする

タイトルの通り。たとえば、自作アプリで生成された画像をそのままGitHubにドロップして画像を登録する。 っていうことをできるようにしたい。だけど前回の記事だとどうしてもドロップする機能が実装できなくて 困っていたのですができる方法が見つかったので記録しておく。

結論からいうとNSTableViewをうまく利用することでできるようになった。

公式ドキュメント にもあるのですが、Draggingの操作があらかじめ用意されていてすくない実装で目的のことができるようになります。

Setup

NSTableViewは初期化されていることは前提で、それ以外で必要な設定を説明します。

1
2
let types = [NSImage.imagePasteboardTypes()]
tableView.registerForDraggedTypes(types)

これはドロップできるデータのデータのタイプを指定します。 この場合だと画像の種類を指定しています。

1
tableView.setDraggingSourceOperationMask(NSDragOperation.Copy, forLocal: false)

これは、ドラッグできる操作の種類、他のWindowにもドラッグできるかどうかも指定できます。 この場合だとファイルのコピーを他のWindowにドロップします。

ドラッグの種類はここ にすべて記述してあります。

NSTableViewDataSource

今回は一つだけ表示できればいいので要素を一つのみ表示する処理をします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// MARK: - NSTableViewDataSource

func numberOfRowsInTableView(tableView: NSTableView) -> Int {
    return 1
}

func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
    var view = tableView.makeViewWithIdentifier("imageCell", owner: self) as NSView

    self.entity = Entity()
    var imageView = view.viewWithTag(1) as NSImageView
    imageView.image = self.entity.image

    return view
}

func tableView(tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? {
     return self.entity
}

データを管理するEntityを作成

TableViewを扱うというとはCellが必要になってそこに描画するデータが必要になります。 今回はそのデータを管理するクラスを作成して、そこにドラッグするデータを保持します。 さらにそのデータをドロップしたときの処理もNSPasteboardWritingを宣言して実装していきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Class Entity: NSObject, NSPasteboardWriting {


    (..snip..)


    var fileURL:NSURL!

    // MARK: - NSPasteboardWriting

    func writableTypesForPasteboard(pasteboard: NSPasteboard!) -> [AnyObject]! {
        return self.fileURL.writableTypesForPasteboard(pasteboard)
    }

    func pasteboardPropertyListForType(type: String!) -> AnyObject! {
        return self.fileURL.pasteboardPropertyListForType(type)
    }

    func writinOptionsForType(type: String!, pasteboard: NSPasteboard!) -> NSPasteboardWritingOptions {
        return self.fileURL.writingOptionsForType(type, pasteboard: pasteboard)
    }
}

ここではファイルのパスをPasteboardにファイルURLのデータをどの型でどのオブジェクトを返すのかを実装しています。 NSURLがNSPasteboardWritingの実装をしてくれているのでそのまま返せば問題ありません。

まとめ

これで画像をドラッグしてFinder等にドロップして画像を保存することが可能になりました。 今回はNSTableViewを利用して目的を実現できましたが、まわりくどいやりかたしなくてもできそうな気はぬぐいきれないのです。 単純にNSView側にドラッグとドロップの処理実装できればシンプルになりそうな気がした今日この頃です。それができると信じて 調査したんだけどリタイヤしたのが前回の記事の話でした。

参考