• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: drag & drop objects
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: drag & drop objects


  • Subject: Re: drag & drop objects
  • From: Jerry Krinock <email@hidden>
  • Date: Tue, 3 Jul 2007 14:35:31 -0700


On 2007 Jul, 03, at 7:16, Ken Tozier wrote:


On Jul 3, 2007, at 10:06 AM, Joe Wildish wrote:

Hi Ken,

If I'm doing drag-and-drop within the same application, I often have some kind of instance variable somewhere that stores reference to the item being dragged. Once the drag is complete, I have the method query the instance variable, rather than the pasteboard. That way I can avoid the pasteboard all together.

How do you avoid the pasteboard?

See code below

The "dragImage:at:offset:event:pasteboard:source:slideBack:" method requires a pasteboard. Do you just create a dummy one and ignore it?

My implementation does not use a custom icon, so I didn't run into this issue, but yes that's what I would do.


I would think that, at the very least, the drag target would need to know what type of data is being dropped so it highlights correctly and can decide to handle the drop or not...

Yes, it knows what's being dragged because it's your got your "behind the scenes pasteboard".


Here is the drag-and-drop code from my NSOutlineView's data source, written for Jaguar/Panther. My "behind the scenes pasteboard" is [[NSApp delegate] intraAppDragArray]. You should be able to see it works. Note in particular the comment at line 17...some types of data are not serializable, and so the "behind the scenes pasteboard" may be your only choice.

// ***** Dragging and Dropping (These must be here, in a NSTable/ OutlineView's dataSource!!) ***** //

// Dragging Source: Writing TO the System Dragging Pasteboard
- (BOOL)outlineView:(NSOutlineView*)olv
         writeItems:(NSArray*)items
       toPasteboard:(NSPasteboard*)pasteboard
{
    NSArray* acceptableDragTypes
    = [NSArray arrayWithObjects:
        SSBookmarkPboardType,
        NSStringPboardType,
        //@"NeXT plain ascii pasteboard type",
        //NSFilenamesPboardType,
        //NSURLPboardType,
        nil];
    [pasteboard declareTypes:acceptableDragTypes owner:self];

// The following does not work because of the @"Parent" key in each item, which is an NSValue.
// success1 = [pboard setPropertyList:writeItems forType:SSBookmarkPboardType] ;
// NSValues are not supported for serialization. Therefore, even though setPropertyLost:forType will return YES,
// it is in fact not successful. The pasteboard will contain NULL for type SSBookmarkPboardType


    // So, we do this instead
    [[NSApp delegate] setIntraAppDragArray:items] ;

    // Now, we set the urls onto the pasteboard for other apps
    // Set NSStringPBoardType data onto pasteboard
    NSString* urls = [items urlsFormattedAsList] ;
    if (urls) {
        [pasteboard setString:urls forType:NSStringPboardType];
    }

    return YES ;
}

/* // Here is an implementation (from Hilleglass) for doing the same thing/
// if this were a table view instead of an outline view.
- (BOOL)tableView:(NSTableView *)tv writeRows:(NSArray*)rows
toPasteboard:(NSPasteboard*)pb
{
NSMutableArray *rowArray = [[NSMutableArray alloc] init];
NSEnumerator *enumerator = [rows objectEnumerator];
id object;
NSData *rowData;
while (object = [enumerator nextObject]) {
int theRow = [object intValue];
NSMutableDictionary *rowRecord = [[self model] recordForRow:theRow];
[rowArray addObject:rowRecord];
}
rowData = [self encodeDataRepresentationForObjects:rowArray];
[pb declareTypes:[NSArray arrayWithObjects:MY_DRAG_TYPE, nil] owner:self];
return [pb setData:rowData forType:MY_DRAG_TYPE];
}
*/



// This is to OK the proposed drop before it happens
- (NSDragOperation)outlineView:(NSOutlineView*)outlineView
validateDrop:(id <NSDraggingInfo>)info // contains payload item(s)
proposedItem:(id)proposedTarget
proposedChildIndex:(int)proposedIndex // location within target item
{
NSPasteboard* pboard = [info draggingPasteboard];
NSDragOperation output = NSDragOperationMove | NSDragOperationCopy ; // Start by assuming it will work
BmLocation* target = [[BmLocation alloc] initWithParent:proposedTarget index:proposedIndex] ;


    // NSLog(@"************ VALIDATE *******************") ;
    //  1. Disallow drops onto empty lines at end of table
    {
        if(!proposedTarget)
            output = NSDragOperationNone;
    }

// 2. Disallow drops which depend on the Pboard type
if (output != NSDragOperationNone) {
if([pboard availableTypeFromArray:[NSArray arrayWithObjects:SSBookmarkPboardType, NSFilenamesPboardType, nil]]) {
// // a. Disallow drops of bookmarks, containers or files onto bookmarks
// SSLog(5, "considering validating of drop of SSBookmarkPboardType or NSFilenames PboardType") ;
// if ([proposedTarget nodeType] == SSBookmark) {
// output = NSDragOperationNone ;
// }
}
else if([pboard availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]]) {
// b. Disallow drops of text strings onto folders or separators; drops onto bookmarks are OK
SSLog(5, "considering validating drop of NS plain ascii pasteboard type") ;
if (![proposedTarget nodeType] == SSBookmark) {
output = NSDragOperationNone ;
}
}
else
{
// c. Disallow drops of unknown types!
SSLog(4, "This app does not take drops of these types: % @", [pboard types]) ;
output = NSDragOperationNone ;
}
}


// 3. Check if OK to insert proposed items at proposed location
if (output != NSDragOperationNone) {
if (![[NSApp delegate] checkOKToInsertItems:[[NSApp delegate] intraAppDragArray] atBmLocation:target]) {
output = NSDragOperationNone ;
}
}


// 4. Now see if we want to retarget it
// Here, we only do retargetting which does not depend on the payloadItem.
// In outlineView:acceptDrop:item:childIndex, we may do additional retargetting per payload item.
if (output != NSDragOperationNone) {
[target retargetIfNeededCheckRange:YES] ;
// We send a message to the outline view to do the retargetting (this seems strange, but it works).
[[[[self doc] mainWindowController] bookmarksOutlineView] setDropItem:[target parent] dropChildIndex:[target index]] ;
// Note: -retargetIfNeededCheckRange: will be invoked again later, when outlineView:acceptDrop:item:childIndex sends
// -[ApplicationController parentingAction:items:toParents:targetItem:atIndexes:] because this method
// does it for clipboard copies and contextual menu Copy To and Move To items. But we also "pre-do" it
// in this case of drag/dropping, to give visual feedback to the user. Also, in the later case we do
// not CheckRange
}


    [target release] ;

    return output ;
}


// This is to actually accept the drop
- (BOOL)outlineView:(NSOutlineView *)outlineView
acceptDrop:(id <NSDraggingInfo>)info
item:(id)targetItem
childIndex:(int)proposedIndex
{
SSLog(5, "outlineView:acceptDrop") ;
NSPasteboard *pboard = [info draggingPasteboard];
NSDragOperation dragOperation = [info draggingSourceOperationMask] ;
BOOL result ;


    enum SSParentingAction action ;

    if ((dragOperation & NSDragOperationMove) > 0)
    {
        action = SSParentingMove ;
    }
    else
    {
        action = SSParentingCopy ;
    }

if([pboard availableTypeFromArray:[NSArray arrayWithObject:SSBookmarkPboardType]])
{
SSLog(5, "Got a drop of type SSBookmarkPboardType") ;
NSArray *payloadItems = [[NSApp delegate] intraAppDragArray] ;


[[NSApp delegate] parentingAction:action
items:payloadItems
toParents:targetItem
atIndexes:[NSNumber numberWithInt:proposedIndex]] ;
result = YES ;


}
else if([pboard availableTypeFromArray:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]])
// Important: We have to test for this before NSStringPboardType because a .webloc file
// generated by Safari in Jaguar seems to have the NSStringPboardType also.
{
NSArray *paths = [pboard propertyListForType:NSFilenamesPboardType];
if (gLogging >=5)
{
SSLog(5, "Got a drop of %i files with paths:", [paths count]) ;
NSEnumerator* e1 = [paths objectEnumerator] ;
NSString* path ;
while ((path = [e1 nextObject]))
{
SSLog(5, " PATH:\"%@\"", path) ;
}
SSLog(5, "\n") ;
}


        NSArray* filenamesAndURLs ;
        if (( filenamesAndURLs = SSWeblocFilenamesAndURLs(paths) ))
        {
            SSLog(5, "got filenamesAndURLs:\n%@", filenamesAndURLs) ;

NSEnumerator *e = [filenamesAndURLs objectEnumerator] ;
NSDictionary* filenameAndURL ;
BmItem* newBookmark ;
NSMutableArray* newBookmarks = [[NSMutableArray alloc] init] ;
while ((filenameAndURL = [e nextObject]))
{
// Low-level methods which create a temporary bookmark:
newBookmark = [[BmItem alloc] initWithNodeType:SSBookmark] ;
[newBookmark setName:[filenameAndURL objectForKey:@"filename"]] ;
[newBookmark setUrl:[filenameAndURL objectForKey:@"url"]] ;


[newBookmarks addObject:newBookmark] ;
[newBookmark release] ;
}
// High-level method which adds them to the tree. Undoable, Redoable, Shows, Tells:
[[NSApp delegate] parentingAction:SSParentingAdd
items:newBookmarks
toParents:targetItem
atIndexes:[NSNumber numberWithInt:proposedIndex]] ;
[newBookmarks release] ;


            [NSApp activateIgnoringOtherApps:YES] ;
            result = YES ;
        }
        else {
            result = NO ;
        }

}
else if([pboard availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]])
{
SSLog(5, "Got a drop of type NeXT plain ascii pasteboard type") ;
NSString* newURL = [pboard stringForType:NSStringPboardType] ;
if (newURL) {
// High-level method which provides Undoable, Redo, Show and Tell:
[[NSApp delegate] changeObjectProperty:KEY_URL
ofItem:targetItem
toObject:newURL] ;


        }
        [NSApp activateIgnoringOtherApps:YES] ;
        result = YES ;
    }
    else {
        SSLog(3, "Sorry, got a drop of a type we cannot handle.") ;
        result = NO ;
    }

    return result;
}

_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


References: 
 >drag & drop objects (From: Ken Tozier <email@hidden>)
 >Re: drag & drop objects (From: Joe Wildish <email@hidden>)
 >Re: drag & drop objects (From: Ken Tozier <email@hidden>)

  • Prev by Date: Re: NSPopupButton in main window changes when NSUserDefaultsController adds/removes item in Preference Pane
  • Next by Date: Re: Cocoa and dead-code stripping
  • Previous by thread: Re: drag & drop objects
  • Next by thread: outdated link in Cocoa documentation
  • Index(es):
    • Date
    • Thread