larod
larod

Reputation: 435

Adjusting coordinates for NSTableView draggingSession

I've been banging my head to the wall for about two weeks, I've looked at all the Apple documentation available plus hundreds of websites looking for a hint to solve my problem. I'm implementing:

-(void)tableView:(NSTableView *)tableView draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint forRowIndexes:(NSIndexSet *)rowIndexes

The problem that I'm having is that the icon for the dragged files shows up in a different coordinate system and I can't seem to find a way to make the icon show on the screenPoint where the drag began. I've looked into all [tableView convert* ] methods in several combinations without success. Below is the code I'm currently using.

-(void)tableView:(NSTableView *)tableView draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint forRowIndexes:(NSIndexSet *)rowIndexes {

[session enumerateDraggingItemsWithOptions:NSDraggingItemEnumerationConcurrent
                                   forView:tableView
                                   classes:[NSArray arrayWithObjects:[NSPasteboardItem class], nil]
                             searchOptions:nil
                                usingBlock:^(NSDraggingItem *draggingItem, NSInteger index, BOOL *stop)
 {
     NSMutableArray *videos = [NSMutableArray array];
     for (Video* video in [_arrayController selectedObjects]) {
         [videos addObject:video.url];
     }

     NSImage *draggedImage = [[NSWorkspace sharedWorkspace]iconForFiles:videos];
     NSPoint mouseLocInView = [tableView convertPoint:[tableView.window convertRectFromScreen:NSMakeRect(screenPoint.x,screenPoint.y, 0, 0)].origin fromView:nil];

     NSLog(@"Mouse location in view: X: %f, Y: %f",mouseLocInView.x, mouseLocInView.y);
     NSLog(@"Screen point: X: %f, Y:%f", screenPoint.x, screenPoint.y);

     NSRect rect = NSMakeRect(0, 0, 50, 50);
     rect.origin =draggingItem.draggingFrame.origin;
     [draggingItem setDraggingFrame:rect contents:draggedImage];
     session.draggingFormation = NSDraggingFormationDefault;
 }];}

Upvotes: 2

Views: 821

Answers (1)

Yann Bizeul
Yann Bizeul

Reputation: 463

I finally got it after thoroughly reading the documentation.

The doc for - enumerateDraggingItemsWithOptions:forView:classes:searchOptions:usingBlock: says that "forView:" argument is the view on which the coordinate system should be based for each NSDraggingItem passed. Pass nil for screen coordinate system.

What is very confusin is I was debugging by logging draggingFrame on draggingItem and couldn't figure out what frame it was. Well, it doesn't matter what is in there, if you pass nil as a view, you can set the dragging frame as screen based coordinates, the same you get when calling session.draggingLocation.

#define DRAG_IMAGE_WIDTH 48
#define DRAG_IMAGE_HEIGHT 48

- (void)tableView:(NSTableView *)tableView
  draggingSession:(NSDraggingSession *)session
 willBeginAtPoint:(NSPoint)screenPoint
    forRowIndexes:(NSIndexSet *)rowIndexes {

    NSImage *image = [NSImage imageNamed:@"tunnelfile"];

    [session enumerateDraggingItemsWithOptions:NSDraggingItemEnumerationConcurrent
                                       forView:nil
                                       classes:[NSArray arrayWithObject:[NSPasteboardItem class]]
                                 searchOptions:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:NSPasteboardURLReadingFileURLsOnlyKey ]
                                    usingBlock:^(NSDraggingItem *draggingItem, NSInteger idx, BOOL *stop)
     {
         [draggingItem setDraggingFrame:NSMakeRect(session.draggingLocation.x-20,
                                                   session.draggingLocation.y-DRAG_IMAGE_HEIGHT+20,
                                                   DRAG_IMAGE_WIDTH,
                                                   DRAG_IMAGE_HEIGHT)
                               contents:image];
     }];
}

Upvotes: 5

Related Questions