GuiDupas
GuiDupas

Reputation: 1701

Swift OSX - Rearrange NSCollectionView with drag and drop not working

I am trying to rearrange the item inside a NSCollectionView but it's not working. It doesn't call some delegate methods as validate drop and accept drop. It calls func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? or func collectionView(_ collectionView: NSCollectionView, writeItemsAt indexPaths: Set<IndexPath>, to pasteboard: NSPasteboard) -> Bool, but after that is doesn't call the other methods.

I think the problem is that I am bot being able to register the correct types for the drag and drop because when I move the items inside the collection view it doesn't show a place where the items can be dropped and after I drop it the items bounce back to their original places.

Here is the code:

FotoProdutoLojaCollectionViewItem.swift import Cocoa

class FotoProdutoLojaCollectionViewItem: NSCollectionViewItem {

    @IBOutlet weak var fotoProdutoLojaImageView: NSImageView!
    @IBOutlet weak var fotoCapaImageView: NSImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        fotoCapaImageView.isHidden = true
    }

}

The items of the CollectionView

func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {

        var item = NSCollectionViewItem()

        item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "FotoProdutoLojaCollectionViewItem"), for: indexPath)

        let fotosProdutoLojaCollectionViewItem = item as! FotoProdutoLojaCollectionViewItem

        produtoLoja?.fotos[indexPath.item].foto?.getDataInBackground(block: {
            (data: Data?, error: Error?) -> Void in

            if error == nil {
                fotosProdutoLojaCollectionViewItem.fotoProdutoLojaImageView.image = NSImage(data: data!)
            }
        })

        if produtoLoja!.fotos[indexPath.item].imagemCapa {
            fotosProdutoLojaCollectionViewItem.fotoCapaImageView.isHidden = false
        }else {
            fotosProdutoLojaCollectionViewItem.fotoCapaImageView.isHidden = true
        }

        return item
    }


override func viewDidLoad() {
        super.viewDidLoad()

        fotosProdutoLojaCollectionView.delegate = self
        fotosProdutoLojaCollectionView.dataSource = self
        fotosProdutoLojaCollectionView.registerForDraggedTypes([NSPasteboard.PasteboardType(kUTTypeData as String)])

        fotosProdutoLojaCollectionView.setDraggingSourceOperationMask(.move, forLocal: true)
    }

Here is the pasteboardWriterForItemAt indexPath. I have tried all the commented lines.

func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? {

    let pb = NSPasteboardItem()

    var data: Data?
    do {
        try data = produtoLoja?.fotos[indexPath.item].foto?.getData()
    } catch {

    }
    pb.setData(data!, forType: NSPasteboard.PasteboardType.string)

    return pb

    //return NSPasteboardItem()
    //return data as? NSPasteboardWriting
}

And here is the writeItemsAt indexPaths.

func collectionView(_ collectionView: NSCollectionView, writeItemsAt indexPaths: Set<IndexPath>, to pasteboard: NSPasteboard) -> Bool {

    return true
}

Upvotes: 0

Views: 1240

Answers (1)

GuiDupas
GuiDupas

Reputation: 1701

A lot of methods were wrong. Here is the corrected code (just the parts related to the collection view delegate and data source to drag and drop items):

ViewDidLoad

var indiceItensMovidosDrag: Set<IndexPath> = []

override func viewDidLoad() {
        super.viewDidLoad()

        fotosProdutoLojaCollectionView.delegate = self
        fotosProdutoLojaCollectionView.dataSource = self
        fotosProdutoLojaCollectionView.registerForDraggedTypes([NSPasteboard.PasteboardType(kUTTypeItem as String)])

        fotosProdutoLojaCollectionView.setDraggingSourceOperationMask(.move, forLocal: true)

        if produtoLoja == nil {
            produtoLoja = ProdutoLoja()
        }
}

Now the delegate and data source methods methods

func numberOfSections(in collectionView: NSCollectionView) -> Int {

        return 1
    }

    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {

        return produtoLoja!.fotos.count
    }

    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {

        var item = NSCollectionViewItem()

        item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "FotoProdutoLojaCollectionViewItem"), for: indexPath)

        let fotosProdutoLojaCollectionViewItem = item as! FotoProdutoLojaCollectionViewItem

        produtoLoja?.fotos[indexPath.item].foto?.getDataInBackground(block: {
            (data: Data?, error: Error?) -> Void in

            if error == nil {
                fotosProdutoLojaCollectionViewItem.fotoProdutoLojaImageView.image = NSImage(data: data!)
            }
        })

        if produtoLoja!.fotos[indexPath.item].imagemCapa {
            fotosProdutoLojaCollectionViewItem.fotoCapaImageView.isHidden = false
        }else {
            fotosProdutoLojaCollectionViewItem.fotoCapaImageView.isHidden = true
        }

        return item
    }

func collectionView(_ collectionView: NSCollectionView, canDragItemsAt indexPaths: Set<IndexPath>, with event: NSEvent) -> Bool {

        return true
    }

    func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? {

        let retorno = NSPasteboardItem()

        var data: Data?
        do {
            try data = produtoLoja?.fotos[indexPath.item].foto?.getData()
        } catch {

        }

        retorno.setData(data!, forType: NSPasteboard.PasteboardType(kUTTypeItem as String))

        return retorno
    }

    func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItemsAt indexPaths: Set<IndexPath>) {

        indiceItensMovidosDrag = indexPaths
    }

    func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, dragOperation operation: NSDragOperation) {

        indiceItensMovidosDrag = []
    }

    func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer<NSIndexPath>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionView.DropOperation>) -> NSDragOperation {

        if proposedDropOperation.pointee == NSCollectionView.DropOperation.on {
            proposedDropOperation.pointee = NSCollectionView.DropOperation.before
        }

        return NSDragOperation.move
    }

    func collectionView(_ collectionView: NSCollectionView, acceptDrop draggingInfo: NSDraggingInfo, indexPath: IndexPath, dropOperation: NSCollectionView.DropOperation) -> Bool {

        var retorno = true

        if indiceItensMovidosDrag.count == 1 {
            for indice in indiceItensMovidosDrag {
                collectionView.animator().moveItem(at: indice, to: (indexPath.item <= indice.item) ? indexPath : (IndexPath(item: indexPath.item - 1, section: 0)))

            }
        } else {
            mostrarErro(mensagem: "Erro", informativo: "Só é possível mover uma imagem por vez")
            retorno = false
        }

        //fotosProdutoLojaCollectionView.reloadData()

        return retorno
    }

Upvotes: 1

Related Questions