Finder and other apps won't accept drag from NSImageView

Discussion in 'Mac Programming' started by benkenobi, Mar 26, 2011.

  1. benkenobi macrumors member

    May 27, 2009
    I've been trying to make it so that an image can be dragged out of NSImageView and onto Finder etc(the destination).

    I've went over the documentation for drag and drop many times but everything seems to be in place. I even copied a sample which does just about the same thing as my program and it still won't show a green + sign when dragging over Finder. The plus sign shows only when I drag over the NSImageView

    The code here is copied over from the sample program which works without a problem. :confused: Can anyone give a hint on what might be missing?
    @implementation MAImageView
    - (id)initWithCoder:(NSCoder *)coder
         Init method called for Interface Builder objects
        if(self==[super initWithCoder:coder]){
            //register for all the image types we can display
            [self registerForDraggedTypes:[NSImage imagePasteboardTypes]];
        return self;
    -(BOOL) acceptsFirstMouse:(NSEvent *)theEvent{
        return YES;
    -(void)mouseDown:(NSEvent *)theEvent{
         catch mouse down events in order to start drag
        //get the Pasteboard used for drag and drop operations
        NSPasteboard* dragPasteboard=[NSPasteboard pasteboardWithName:NSDragPboard];
        //create a new image for our semi-transparent drag image
        NSImage* dragImage=[[NSImage alloc] initWithSize:[[self image] size]]; 
        //add the image types we can send the data as(we'll send the actual data when it's requested)
        [dragPasteboard declareTypes:[NSArray arrayWithObject: NSTIFFPboardType] owner:self];
        [dragImage lockFocus];//draw inside of our dragImage
        //draw our original image as 50% transparent
        [[self image] dissolveToPoint: NSZeroPoint fraction: .5];
        [dragImage unlockFocus];//finished drawing
        [dragImage setScalesWhenResized:YES];//we want the image to resize
        [dragImage setSize:[self bounds].size];//change to the size we are displaying
        //execute the drag
        [self dragImage: dragImage//image to be displayed under the mouse
                     at: [self bounds].origin//point to start drawing drag image
                 offset: NSZeroSize//no offset, drag starts at mousedown location
                  event:theEvent//mousedown event
             pasteboard:dragPasteboard//pasteboard to pass to receiver
                 source: self//object where the image is coming from
              slideBack: YES];//if the drag fails slide the icon back
        [dragImage release];//done with our dragImage
    - (void)pasteboard:(NSPasteboard *)sender provideDataForType:(NSString *)type
         method called by pasteboard to support promised 
         drag types.
        //sender has accepted the drag and now we need to send the data for the type we promised
        if([type compare: NSTIFFPboardType]==NSOrderedSame){
            //set data for TIFF type on the pasteboard as requested
            [sender setData:[[self image] TIFFRepresentation] forType:NSTIFFPboardType];
        }else if([type compare: NSPDFPboardType]==NSOrderedSame){
            [sender setData:[self dataWithPDFInsideRect:[self bounds]] forType:NSPDFPboardType];
    - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal{
        return NSDragOperationGeneric;//destination object is in a different application.
  2. robbieduncan Moderator emeritus


    Jul 24, 2002
    Does the Finder support the types you are offering? I would expect the Finder only accepts files, or possibly file names, not image data. i.e. the Finder will accept an image if it's a file but it will not create a file for you from image data.

    What happens if you promise the type NSFileContentsPboardType? Do you get messages in pasteboard:provideDataForType: ?
  3. benkenobi, Mar 26, 2011
    Last edited: Mar 26, 2011

    benkenobi thread starter macrumors member

    May 27, 2009
    EDIT: works with Finder now!

    Changed: return NSDragOperationGeneric; to return NSDragOperationCopy;
    - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal{
            return NSDragOperationCopy;//destination object is in a different application.
            return NSDragOperationNone;

    Making progess.

    I rewrote the code so it's all done with file names like you suggested. I can drop into texteditor and other programs but not Finder. hmm

    -(void)mouseDown:(NSEvent *)theEvent{
        NSURL *fileURL;
        NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
        //get fileURL of dragged image
        [[self image] initWithPasteboard:pboard];
        fileURL=[NSURL URLFromPasteboard:pboard];
        NSString *filePath1= [fileURL path];
        NSImage *dragImage;
        NSPoint dragPosition;
        // Write data to the pasteboard
        NSArray *fileList = [NSArray arrayWithObjects:filePath1, nil];
        pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
        [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
        [pboard setPropertyList:fileList forType:NSFilenamesPboardType];
        // Start the drag operation
        dragImage = [[NSWorkspace sharedWorkspace] iconForFile:filePath1];
        dragPosition = [self convertPoint:[theEvent locationInWindow]
        dragPosition.x -= 16;
        dragPosition.y -= 16;
        [self dragImage:dragImage

Share This Page