2
votes

I understand how to get drag and drop working for NSCollectionView but I can't seem to stop it 'lifting' the items off the view.

My current solution is to not implement

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

from NSCollectionViewDelegate to ensure that

func collectionView(_ collectionView: NSCollectionView, draggingImageForItemsAt indexPaths: Set<IndexPath>, with event: NSEvent, offset dragImageOffset: NSPointPointer) -> NSImage

IS called, where I can provide my own dragging images. However, these do not flock or provide the icon showing how many items are being dragged.

The problem is that when I implement the former method, nothing I seem to do (including overriding the NSCollectionViewItem's draggingImageComponents) seems to prevent the drag 'lifting' the item off the collection view, leaving behind an empty space.

Dragging images in Photos.app and files in Finder.app (icon view) do not lift the item so hopefully this is possible.

1
lldb + hopper shows it is a custom implementation of dragging imgur.com/a/BSBqOUzMarek H
Wow! Thanks so much for investigating this. I take it this means I can't do something similar with public APIs?Rik
I was checking Preview.app which has PVSidebarThumbnailController where you can do the same. It only uses public functions. So yes it's possible with public. Use Hopperapp to look inside. Also lldb to set breakpoints (-n or -a). Also set flag to debug types for items in pasteboard (Preview) using po [NSUserDefaults standardUserDefaults] setValue:@(4) forKey:@"NSDragManagerLogLevel"]. It takes too much time to replicate the feature. It shouldn't be hard to look at Apple's pseudocode in hopper to understand what is going on. imgur.com/a/15VCVtI (Photos.app pasteboarditems)Marek H
Did you resolve this?Stuart Carnie
No. In the end, I made my own stack of selected items.Rik

1 Answers

4
votes

This appears to be essentially the same question as NSCollectionView - dragging shows a “hole” - want it to look like the Finder

My initial solution was to use a custom view for the collection view item. In my subclass I override setHidden: to prevent the collection view from hiding my item view while the item is being dragged. This had some undesirable side-effects. It appears that NSCollectionView also hides item views when changing the layout.

The next idea (so far) works fine in my application. I un-hide the item views when dragging starts.

@interface HGImagesCollectionViewDelegate : NSObject <NSCollectionViewDelegate>

@end

@implementation HGImagesCollectionViewDelegate

- (void)collectionView:(NSCollectionView *)collectionView
       draggingSession:(NSDraggingSession *)session
      willBeginAtPoint:(NSPoint)screenPoint
  forItemsAtIndexPaths:(NSSet<NSIndexPath *> *)indexPaths
{
    //  Prevent item from being hidden (creating a hole in the grid) while being dragged
    for (NSIndexPath *indexPath in indexPaths) {
        [[[collectionView itemAtIndexPath:indexPath] view] setHidden:NO];
    }

    // …

}  

@end