Re: drag & drop objects
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