NSCollectionView Drag and Drop: Most delegate events not triggered

I have an NSCollectionView associated with an NSArrayController. I want to work with drag and drop, so I create a delegate and implement methods

-(BOOL)collectionView:(NSCollectionView *)collectionView canDragItemsAtIndexes:(NSIndexSet *)indexes withEvent:(NSEvent*)event -(BOOL)collectionView:(NSCollectionView *)collectionView acceptDrop:(id < NSDraggingInfo >)draggingInfo index:(NSInteger)index dropOperation:(NSCollectionViewDropOperation)dropOperation -(NSDragOperation)collectionView:(NSCollectionView *)collectionView validateDrop:(id < NSDraggingInfo >)draggingInfo proposedIndex:(NSInteger *)proposedDropIndex dropOperation:(NSCollectionViewDropOperation *)proposedDropOperation -(NSArray *)collectionView:(NSCollectionView *)collectionView namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropURL forDraggedItemsAtIndexes:(NSIndexSet *)indexes 

I am returning YES for two BOOL methods, NSDragOperationMove for the validateDrop: method and an empty array for the namesOfPromisedFilesDroppedAtDestination: method. I also have an NSLog statement as the first line in each method, so I can see when they are called.

Currently, the only method that is called is canDragItemsAtIndexes: (where I return YES). I see that it is called, but any further drag and drop just changes the selection. The rest are never called.

If I make NSCollectionView not support selection, then even this method is not called.

I am sure that I am missing something beyond the obvious, but I cannot understand what it is. Has anyone got drag and drop while working with NSCollectionViews, and can shed some light?

+6
source share
2 answers

I think you missed the part where you write drag and drop content on cardboard.
To support drag and drop, you need to follow these steps:

  • Determine if you can drag a drag source
  • If YES , write the contents in the pasteboard
  • Confirm and accept items in destination folder

Writing on cardboard should be implemented in
- collectionView:writeItemsAtIndexes:toPasteboard:

You also need to register your draggable types - registerForDraggedTypes:

Sample code: http://developer.apple.com/library/mac/#samplecode/IconCollection/Introduction/Intro.html

+4
source

This code has everything I need to drag an image from one NSCollectionView to another. Assuming this was NOT super obvious. Selectable is checked for viewing a collection of sources and connects to data sources and delegates, but I do not need registerForDraggedTypes.

 class Window:NSWindow, NSComboBoxDelegate, NSTextFieldDelegate, NSDatePickerCellDelegate, NSTableViewDataSource, NSTableViewDelegate, MKMapViewDelegate, NSCollectionViewDataSource, NSCollectionViewDelegate, NSCollectionViewDelegateFlowLayout, NSTabViewDelegate, NSMenuDelegate, NSDraggingDestination { } func collectionView(collectionView: NSCollectionView, writeItemsAtIndexPaths indexPaths: Set<NSIndexPath>, toPasteboard pasteboard: NSPasteboard) -> Bool { let index = indexPaths.first!.item let url = webImageURLs[index] // array of string URLs that parallels the collection view. NSPasteboard.generalPasteboard().clearContents() NSPasteboard.generalPasteboard().declareTypes([kUTTypeText as String, kUTTypeData as String], owner: nil) NSPasteboard.generalPasteboard().setString(url, forType: (kUTTypeText as String)) NSPasteboard.generalPasteboard().setData(webImageData[index], forType: (kUTTypeData as String)) return true } // Provide small version of image being dragged to accompany mouse cursor. func collectionView(collectionView: NSCollectionView, draggingImageForItemsAtIndexPaths indexPaths: Set<NSIndexPath>, withEvent event: NSEvent, offset dragImageOffset: NSPointPointer) -> NSImage { let item = collectionView.itemAtIndex(indexPaths.first!.item) return (item?.imageView?.image)!.resizeImage(20, height: 20) } // Image is dropped on destination NSCollectionView. func collectionView(collectionView: NSCollectionView, draggingSession session: NSDraggingSession, endedAtPoint screenPoint: NSPoint, dragOperation operation: NSDragOperation) { let pasteboardItem = NSPasteboard.generalPasteboard().pasteboardItems![0] let urlString = pasteboardItem.stringForType((kUTTypeText as String)) let imageData = pasteboardItem.dataForType((kUTTypeData as String)) // destinationImages is the data source for the destination collectionView. destinationImageURLs is used to keep track of the text urls. if urlString != nil { destinationImageURLs.insert(urlString!, atIndex: 0) destinationImages.insert(NSImage(data: imageData!)!, atIndex: 0) destinationCollectionView.reloadData() let selectionRect = self.favoritesCollectionView.frameForItemAtIndex(0) destinationCollectionView.scrollRectToVisible(selectionRect) } } extension NSImage { func resizeImage(width: CGFloat, height: CGFloat) -> NSImage { let img = NSImage(size: CGSizeMake(width, height)) img.lockFocus() let ctx = NSGraphicsContext.currentContext() ctx?.imageInterpolation = .High drawInRect(NSRect(x: 0, y: 0, width: width, height: height), fromRect: NSRect(x: 0, y: 0, width: size.width, height: size.height), operation: .CompositeCopy, fraction: 1) img.unlockFocus() return img } } 
0
source

Source: https://habr.com/ru/post/886928/


All Articles