NSTableView, file promises, and the message queue

  • OK, I've searched the archives and found this,
    <http://cocoa.mamasam.com/COCOADEV/2003/03/1/57866.php>, which
    describes my problem exactly, but no one answered.

    I've set up an NSTableView to do drag-and-drop, and it's done by using
    file promises. Since there isn't any way currently to create a file
    promise pasteboard, I'm using the workaround I read about, which is to
    manually call -dragPromisedFilesOfType: within the data source's
    -tableView:writeRows:toPasteboard: method.

    Things work fine, but now I'm having yet another weird problem:
    Drag-and-drop works, but after the drop, the application just "sticks".
    That is, the message queue just stops until the user clicks somewhere
    in the application, and then it magically restarts.

    Is there any workaround or fix for this? I'm using something similar
    (but not the same) as this:

    - (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray *)rows
    toPasteboard:(NSPasteboard *)pboard
    {
        NSPoint dragPosition = [tableView convertPoint:[window
    convertScreenToBase:[NSEvent mouseLocation]] fromView:nil];
        NSRect imageLocation;
        long i;

        // This code sets up the "image" so that it appears directly in the
    center of the cursor.
        dragPosition.x -= 16;
        dragPosition.y -= 16;
        imageLocation.origin = dragPosition;
        imageLocation.size = NSMakeSize(32,32);

        [tableView dragPromisedFilesOfTypes:[NSArray arrayWithObject:@""]
    fromRect:imageLocation source:tableView slideBack:YES event:[NSApp
    currentEvent]];
        return NO;
    }

    Any ideas would be appreciated...

    Nick Zitzmann
    AIM/iChat: dragonsdontsleep
    Check out my software page: http://dreamless.home.attbi.com/

    "Great spirits have always encountered violent opposition from mediocre
    minds." - Albert Einstein
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • I have the same problem too...I've tried many methods of working around
    it, but all lead to quirks such as stalls or odd table view selection
    behaviour...

    Has anyone on the list successfully implemented promise drags for a
    TableView / OutlineView? I think it is an oversight on Apple's part not
    to provide a method for manually adding the promise drag sources to the
    dragging pasteboard, since that would have allowed us to use the
    default method for starting drags from table views.

    / Rgds, David

    On Tuesday, May 13, 2003, at 03:08 PM, Nick Zitzmann wrote:

    > OK, I've searched the archives and found this,
    > <http://cocoa.mamasam.com/COCOADEV/2003/03/1/57866.php>, which
    > describes my problem exactly, but no one answered.
    >
    > I've set up an NSTableView to do drag-and-drop, and it's done by using
    > file promises. Since there isn't any way currently to create a file
    > promise pasteboard, I'm using the workaround I read about, which is to
    > manually call -dragPromisedFilesOfType: within the data source's
    > -tableView:writeRows:toPasteboard: method.
    >
    > Things work fine, but now I'm having yet another weird problem:
    > Drag-and-drop works, but after the drop, the application just
    > "sticks". That is, the message queue just stops until the user clicks
    > somewhere in the application, and then it magically restarts.
    >
    > Is there any workaround or fix for this? I'm using something similar
    > (but not the same) as this:
    >
    > - (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray *)rows
    > toPasteboard:(NSPasteboard *)pboard
    > {
    > NSPoint dragPosition = [tableView convertPoint:[window
    > convertScreenToBase:[NSEvent mouseLocation]] fromView:nil];
    > NSRect imageLocation;
    > long i;
    >
    > // This code sets up the "image" so that it appears directly in
    > the center of the cursor.
    > dragPosition.x -= 16;
    > dragPosition.y -= 16;
    > imageLocation.origin = dragPosition;
    > imageLocation.size = NSMakeSize(32,32);
    >
    > [tableView dragPromisedFilesOfTypes:[NSArray arrayWithObject:@""]
    > fromRect:imageLocation source:tableView slideBack:YES event:[NSApp
    > currentEvent]];
    > return NO;
    > }
    >
    > Any ideas would be appreciated...
    >
    > Nick Zitzmann
    > AIM/iChat: dragonsdontsleep
    > Check out my software page: http://dreamless.home.attbi.com/
    >
    > "Great spirits have always encountered violent opposition from
    > mediocre minds." - Albert Einstein
    > _______________________________________________
    > cocoa-dev mailing list | <cocoa-dev...>
    > Help/Unsubscribe/Archives:
    > http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    > Do not post admin requests to the list. They will be ignored.
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • I have promised file drag&drop working (it was a joyous
    occasion when that happened :-) ), no application sticking.
    It looks like you are trying to fit promised files around the
    more normal drag&drop API, I don't think you can do that,
    I think you have to subclass NSTableView (see below) and
    overload some methods. Don't rely on the Jaguar developer
    CD Cocoa documentation to cover promised files properly,
    it doesn't (well mine doesn't), you have to look at the Apple
    on-line documentation. That is where my code came from.

    There are a couple of slight anomalies in its behaviour, which
    if someone knows how to fix then I'd be glad to hear:

    1. You can't start a drag until your app is at the front, which
    is different to normal drag&drop.
    2. The drag starts immediately rather after a slight mouse
    movement with the button down, i.e. all you have to do is
    click.

    Otherwise it works great, the Finder responds with the path
    of the folder the drag was dropped onto perfectly and (after
    some initial struggling to get it to work) no application sticking.

    Tim.

    @implementation MyTableView

    - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {

        if (isLocal) return NSDragOperationNone;
        else return NSDragOperationCopy;
    }

    - (void)mouseDown:(NSEvent *)theEvent
    {
        NSPoint dragPosition;
        NSRect imageLocation;
        int row;

        dragPosition = [self convertPoint:[theEvent locationInWindow]
    fromView:nil];

        row = [self rowAtPoint:dragPosition];

        if ( (row != -1) && (row < [[self delegate] nRows]) ) {

    [self selectRow:row byExtendingSelection:NO];

    dragPosition.x -= 16;
    dragPosition.y -= 16;
    imageLocation.origin = dragPosition;
    imageLocation.size = NSMakeSize( 32, 32 );

    printf ( "mouseDown: called (x: %f, y:%f, row:%d)\n", dragPosition.x,
    dragPosition.y, row );

    [self dragPromisedFilesOfTypes:[NSArray arrayWithObject:@""]
      fromRect:imageLocation source:self slideBack:YES event:theEvent];
        }
    }

    - (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)url
    {
        printf( "Dropped to: %s\n", [[url path] cString] );

        return nil;
    }

    @end

    On Tuesday, May 13, 2003, at 15:53 Europe/London,
    <cocoa-dev-request...> wrote:

    > OK, I've searched the archives and found this,
    > <http://cocoa.mamasam.com/COCOADEV/2003/03/1/57866.php>, which
    > describes my problem exactly, but no one answered.
    >
    > I've set up an NSTableView to do drag-and-drop, and it's done by using
    > file promises. Since there isn't any way currently to create a file
    > promise pasteboard, I'm using the workaround I read about, which is to
    > manually call -dragPromisedFilesOfType: within the data source's
    > -tableView:writeRows:toPasteboard: method.
    >
    > Things work fine, but now I'm having yet another weird problem:
    > Drag-and-drop works, but after the drop, the application just "sticks".
    > That is, the message queue just stops until the user clicks somewhere
    > in the application, and then it magically restarts.
    >
    > Is there any workaround or fix for this? I'm using something similar
    > (but not the same) as this:
    >
    > - (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray *)rows
    > toPasteboard:(NSPasteboard *)pboard
    > {
    > NSPoint dragPosition = [tableView convertPoint:[window
    > convertScreenToBase:[NSEvent mouseLocation]] fromView:nil];
    > NSRect imageLocation;
    > long i;
    >
    > // This code sets up the "image" so that it appears directly in
    > the
    > center of the cursor.
    > dragPosition.x -= 16;
    > dragPosition.y -= 16;
    > imageLocation.origin = dragPosition;
    > imageLocation.size = NSMakeSize(32,32);
    >
    > [tableView dragPromisedFilesOfTypes:[NSArray arrayWithObject:@""]
    > fromRect:imageLocation source:tableView slideBack:YES event:[NSApp
    > currentEvent]];
    > return NO;
    > }
    >
    > Any ideas would be appreciated...
    >
    > Nick Zitzmann
    > AIM/iChat: dragonsdontsleep
    > Check out my software page: http://dreamless.home.attbi.com/
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • On Tuesday, May 13, 2003, at 09:41  AM, Tim Hewett wrote:

    > I have promised file drag&drop working (it was a joyous
    > occasion when that happened :-) ), no application sticking.
    > It looks like you are trying to fit promised files around the
    > more normal drag&drop API, I don't think you can do that,
    > I think you have to subclass NSTableView (see below) and
    > overload some methods. Don't rely on the Jaguar developer
    > CD Cocoa documentation to cover promised files properly,
    > it doesn't (well mine doesn't), you have to look at the Apple
    > on-line documentation. That is where my code came from.

    I tried your approach and it didn't work.

    First of all, subclassing -mouseDown: and adding the drag stuff makes
    the program assume I'm dragging something as soon as the mouse is down.
    Also, it completely breaks the table view action and double-click
    action, both of which I need to preserve.

    So, I tried subclassing -mouseDragged: and for some reason, the
    subclass method is never called.

    Then, I tried capturing the next event using NSApplication, and that
    appears to block unless I set the expiration date to be [NSDate date],
    which doesn't work.

    So I'm all out of ideas. Has anyone made this work flawlessly? As I
    said before, my solution worked, but I end up with a stalled message
    queue...

    Nick Zitzmann
    AIM/iChat: dragonsdontsleep
    Check out my software page: http://dreamless.home.attbi.com/

    "Great spirits have always encountered violent opposition from mediocre
    minds." - Albert Einstein
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • On Wednesday, May 14, 2003, at 02:06 PM, Nick Zitzmann wrote:

    > On Tuesday, May 13, 2003, at 09:41  AM, Tim Hewett wrote:
    >
    >> I have promised file drag&drop working (it was a joyous
    >> occasion when that happened :-) ), no application sticking.
    >> It looks like you are trying to fit promised files around the
    >> more normal drag&drop API, I don't think you can do that,
    >> I think you have to subclass NSTableView (see below) and
    >> overload some methods. Don't rely on the Jaguar developer
    >> CD Cocoa documentation to cover promised files properly,
    >> it doesn't (well mine doesn't), you have to look at the Apple
    >> on-line documentation. That is where my code came from.
    >
    > I tried your approach and it didn't work.
    >
    > First of all, subclassing -mouseDown: and adding the drag stuff makes
    > the program assume I'm dragging something as soon as the mouse is
    > down. Also, it completely breaks the table view action and
    > double-click action, both of which I need to preserve.
    >
    > So, I tried subclassing -mouseDragged: and for some reason, the
    > subclass method is never called.

    The reason for that is that NSTableView starts event tracking in
    mouseDown: and doesn't stop tracking until the mouse button is
    released. That makes it difficult to overload - since you would have to
    figure out exactly what mouseDown: does except for catching drags.

    > Then, I tried capturing the next event using NSApplication, and that
    > appears to block unless I set the expiration date to be [NSDate date],
    > which doesn't work.
    >
    > So I'm all out of ideas. Has anyone made this work flawlessly? As I
    > said before, my solution worked, but I end up with a stalled message
    > queue...

    I've tried both your approach and the subclassing method, without
    success...Could someone who managed to do it please post some sample
    code?

    / Rgds, David
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • For the problem of the event queue sticking when dragging from the
    datasource: just return YES to the method writeCell... I seem to
    remember that i had to do a few trick after that to keep everything
    working as expected, but that should get rid of the sticking. The only
    problem left is that when dragging, it will behave as if you did two
    drags, one for the promise, one for the regular so you'll sometimes get
    a slide back effect (minor annoyance in my case).

    As for overriding mouse down, you have to set a periodic event so
    you'll know if you need to start a drag or just select or anything else.

    NSEvent startPeriodicEventsAfterDelay: 0.3 withPeriod: 0];
            NSEvent *newEvent = [[self window] nextEventMatchingMask:
                NSLeftMouseUpMask | NSLeftMouseDraggedMask |
    NSPeriodicMask];
            switch ([newEvent type]) {
                case NSLeftMouseUp:
                    break;

                case NSPeriodic:
                    [self doPromiseDrag: theEvent];
                    break;

                case NSLeftMouseDragged:
                    break;

                default:
                    break;

    hope this helps.

    Olivier

    On Wednesday, May 14, 2003, at 07:23  AM, David Remahl wrote:

    > On Wednesday, May 14, 2003, at 02:06 PM, Nick Zitzmann wrote:
    >
    >> On Tuesday, May 13, 2003, at 09:41  AM, Tim Hewett wrote:
    >>
    >>> I have promised file drag&drop working (it was a joyous
    >>> occasion when that happened :-) ), no application sticking.
    >>> It looks like you are trying to fit promised files around the
    >>> more normal drag&drop API, I don't think you can do that,
    >>> I think you have to subclass NSTableView (see below) and
    >>> overload some methods. Don't rely on the Jaguar developer
    >>> CD Cocoa documentation to cover promised files properly,
    >>> it doesn't (well mine doesn't), you have to look at the Apple
    >>> on-line documentation. That is where my code came from.
    >>
    >> I tried your approach and it didn't work.
    >>
    >> First of all, subclassing -mouseDown: and adding the drag stuff makes
    >> the program assume I'm dragging something as soon as the mouse is
    >> down. Also, it completely breaks the table view action and
    >> double-click action, both of which I need to preserve.
    >>
    >> So, I tried subclassing -mouseDragged: and for some reason, the
    >> subclass method is never called.
    >
    > The reason for that is that NSTableView starts event tracking in
    > mouseDown: and doesn't stop tracking until the mouse button is
    > released. That makes it difficult to overload - since you would have
    > to figure out exactly what mouseDown: does except for catching drags.
    >
    >> Then, I tried capturing the next event using NSApplication, and that
    >> appears to block unless I set the expiration date to be [NSDate
    >> date], which doesn't work.
    >>
    >> So I'm all out of ideas. Has anyone made this work flawlessly? As I
    >> said before, my solution worked, but I end up with a stalled message
    >> queue...
    >
    > I've tried both your approach and the subclassing method, without
    > success...Could someone who managed to do it please post some sample
    > code?
    >
    > / Rgds, David
    > _______________________________________________
    > cocoa-dev mailing list | <cocoa-dev...>
    > Help/Unsubscribe/Archives:
    > http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    > Do not post admin requests to the list. They will be ignored.
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • On Wednesday, May 14, 2003, at 07:00  AM, olivier wrote:

    > For the problem of the event queue sticking when dragging from the
    > datasource: just return YES to the method writeCell... I seem to
    > remember that i had to do a few trick after that to keep everything
    > working as expected, but that should get rid of the sticking.

    Hmm, which writeCell: method might this be? We're talking about
    NSTableView, and after searching through the documentation and headers,
    I can only find a writeCell: method for NSTextView. Is there some sort
    of undocumented method I need to implement here?

    Nick Zitzmann
    AIM/iChat: dragonsdontsleep
    Check out my software page: http://dreamless.home.attbi.com/

    "Great spirits have always encountered violent opposition from mediocre
    minds." - Albert Einstein
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • sorry for the imprecision:

    - (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray*)rows
    toPasteboard:(NSPasteboard*)pboard

    - (BOOL)outlineView:(NSOutlineView *)outlineView
    writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard

    Olivier

    On Thursday, May 15, 2003, at 06:58  AM, Nick Zitzmann wrote:

    >
    > On Wednesday, May 14, 2003, at 07:00  AM, olivier wrote:
    >
    >> For the problem of the event queue sticking when dragging from the
    >> datasource: just return YES to the method writeCell... I seem to
    >> remember that i had to do a few trick after that to keep everything
    >> working as expected, but that should get rid of the sticking.
    >
    > Hmm, which writeCell: method might this be? We're talking about
    > NSTableView, and after searching through the documentation and
    > headers, I can only find a writeCell: method for NSTextView. Is there
    > some sort of undocumented method I need to implement here?
    >
    > Nick Zitzmann
    > AIM/iChat: dragonsdontsleep
    > Check out my software page: http://dreamless.home.attbi.com/
    >
    > "Great spirits have always encountered violent opposition from
    > mediocre minds." - Albert Einstein
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.