I'm trying to enable drag&drop for NSOutlineView in my OSX app. The only thing I need to be able to drop is png image from the Finder.
I have myOutlineView and a controller which is a data source and a delegate of my outline view.
In my outline view controller I have these three methods:
-(BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
-(NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
-(BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index{
none of them is being called...my nib is setup properly...my outline view is getting filled and all of the functionality is working except the drag&drop feature...
Any kind of help is highly appreciated!
Just fixed it I placed
[[self currentOutlineView] registerForDraggedTypes:[NSArray arrayWithObjects:(NSString*)kUTTypeFileURL,kPrivateDragUTI,nil]];
to the wrong spot, so my outline view couldn't register the draggable types appropriately. I placed it to
-(void) awakeFromNib
in my outline view controller and everything is working now! :)
Related
I have implemented following delegate to support drag n drop in NSTableView. Delegates validateDrop and acceptDrop are called and I'm able to drag and drop content from Finder to NSTableView however writeRowsWithIndexes is not called when I tried to drag items from NSTableView and drop to Finder.
- (BOOL)tableView:(NSTableView *)aTableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard
{
NSLog(#"writeRowsWithIndexes");
return YES;
}
- (NSDragOperation)tableView:(NSTableView *)aTableView validateDrop:(id < NSDraggingInfo >)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)operation
{
NSLog(#"validateDrop");
return NSDragOperationCopy;
}
- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id < NSDraggingInfo >)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation
{
NSLog(#"acceptDrop");
return YES;
}
I have registered dragging types as
//Registering dragged Types
[tableView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
//To support across application passing NO
[tableView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
//Don't want any highlight selection on drop
[tableView setDraggingDestinationFeedbackStyle:NSTableViewDraggingDestinationFeedbackStyleNone];
Drag is not initiating in my NSTableView, Can anybody tell me what could be the possible reasons? I have custom cell in the TableView and also set delegate and datasource properly.
I found the cause, it was due to Custom cell. I had subclassed my custom cell from NSButtonCell. Dragging is not working on button cell because buttons are not meant for dragging, they are meant for illuminating.
I resolved the issue by sub classing my custom cell from NSActionCell.
Found in the below post:
NSTableView Drag and Drop not working
I'm not able to enable drag and drop for a NSOutlineView. I've implemented the related method of the NSOutlineView Delegate.
But it seems that when I click an item, I can't even dragging it (I don't see animation).
- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index
{
return YES;
}
- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
{
return NSDragOperationMove; //not sure about this one.
}
thanks
UPDATE:
I'm implementing forOSX >= 10.5
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
{
NSString *pasteBoardType = [self pasteboardTypeForTableView:outlineView];
[pboard declareTypes:[NSArray arrayWithObject:pasteBoardType] owner:self];
NSData *rowData = [NSKeyedArchiver archivedDataWithRootObject:items];
[pboard setData:rowData forType:pasteBoardType];
return YES;
}
The methods you implemented are just for the destination of the drag. You still need to implement the dragging source methods. For whatever reason Apple's NSOutlineViewDataSource Protocol documentation is missing these methods but you have two options:
If you are building 10.7+ use Xcode's Open Quickly command to look in NSOutlineView.h and find the relevant methods. Also check out the DragNDropOutlineView sample app.
If you are supporting previous OS's then use NSTableView's delegate methods. See NSTableViewDataSource Protocol Reference. Remember that NSOutlineView is a subclass of NSTableView and can use the table view methods.
At a minimum you will probably want to implement outlineView:writeItems:toPasteboard:
/* Dragging Source Support - Optional for single-image dragging. This method is called after
it has been determined that a drag should begin, but before the drag has been started. To
refuse the drag, return NO. To start a drag, return YES and place the drag data onto the
pasteboard (data, owner, etc...). The drag image and other drag related information will
be set up and provided by the outline view once this call returns with YES. The items array
is the list of items that will be participating in the drag.
*/
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard;
Update:
If the item can be dragged but won't drop on anything then most likely outlineView:validateDrop:proposedItem:proposedChildIndex: is not being called. This would mean you haven't registered the pasteboard type which you do with registerForDraggedTypes:. You would do this somewhere in the view controller, probably in awakeFromNib.
[outlineView registerForDraggedTypes:[NSArray arrayWithObject:#"myPasteBoardType"]];
To move the item (and all its children) modify your model in outlineView:acceptDrop:item:childIndex:. Then send reloadData to the outlineView.
To make your outline view a dragging source, you must implement:
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard;
This should address what you described, but you've got a lot more work to do beyond this.
In my Application i have one NSOutlineView having list of somefiles and one WebView,
User allows to drag any item from the Outline view to WebView, and on that , i am suppose to handle the database transaction,
In the Outline view , i have implemented following methods,
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard{
[self log:#"write Items”];
// Some other code to prepare the Write Item,
}
- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index{
}
- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index{
}
On the WebView side, i have implemented following, methods,
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
NSPasteboard *pboard;
NSDragOperation sourceDragMask;
[self log:#"Inside draggingEntered”];
return NSDragOperationEvery;
}
- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender{
}
- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender{
}
Now when i drag an element from outline view to WebView, i could see, writeItem of Outline view is getting called,
and in the Webview, DragEnter is getting called from where, i am not returning drag operation NONE, but returning NSDragoperationEvery,
The problem is that, i am not getting method, prepareForDragOperation and PerformDragOperation,
Can anyone help me please,
Kind Regards
Rohan
Hi guys
Thanks for Looking over it,
It got resolved by overriding
- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender{
[self log:#"Inside Dragging updated"];
return NSDragOperationEvery;
}
Though in the document it was mentioned as an option and if its not implemented, it will take the return values from dragEnter Method,
perhaps for My own data type, it would have got NONE form WebView method and working once i overwrite it.
Kind Regard
Rohan
Trying to get this to work, and not sure what I'm missing. The idea is to drop images on a NSTableView so that I can grab their paths and do some manipulations for them. I can get the drop to work for NSPastebouardTypeString, but I cannot for the life of me get it to register dragging PNGs from Finder into the tableview. What am I missing?
Relevent code:
- (void)awakeFromNib {
[imageTableView registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypePNG]];
}
- (NSDragOperation)tableView:(NSTableView *)aTableView validateDrop:(id < NSDraggingInfo >)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)operation {
NSLog(#"Validate Drop");
return NSDragOperationEvery;
}
- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id < NSDraggingInfo >)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation {
NSLog(#"Accept Drop");
return YES;
}
PNG files dragged from the Finder are not PNG data. They're files, which have their own pasteboard type. (Being files, you don't necessarily want them to be entirely loaded in memory in case of a drop, would you? :D)
10.4 gave you a NSArray of NSStrings as a NSFilenamesPboardType. 10.5 and later also provide you with an array of file: URLs as NSURLPboardType. Since you're using the older API, this document on 10.5- APIs applies (10.6 completely overhauls the pasteboard API to make it behave more like the iOS one).
Okay, I've got a custom class called "Task", which represents a task to be done. I've got an NSMatrix which acts as a calendar. I want the user to be able to drag an icon from an nscollectionview (I've had no trouble setting up the nscollectionview) onto a cell in the nsmatrix, thereby assigning that task to that day. I just can't seem to get the nsmatrix to respond to the drag or the drop at all.
I've implemented the method:
- (BOOL)collectionView:(NSCollectionView *)cv writeItemsAtIndexes:(NSIndexSet *)indexes toPasteboard:(NSPasteboard *)pasteboard
{
[pasteboard declareTypes:[NSArray arrayWithObject:TASK_UTI] owner:self];
NSUInteger index=[indexes firstIndex];
Task* task=[[cv content] objectAtIndex:index];
NSData* taskData=[NSKeyedArchiver archivedDataWithRootObject:task];
[taskData retain];
BOOL success=[pasteboard setData:taskData forType:TASK_UTI];
return success;
}
in my nscollectionview delegate as shown above.
I've sent [self registerForDraggedTypes:[NSArray arrayWithObjects:TASK_UTI, nil]] in my NSMatrix subclass (called "Calendar").
I've implemented the methods:
- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender
in my Calendar (NSMatrix subclass) class.
Some debugging shows that the NSMatrix/Calendar object is not even running the dragging methods above. What gives?
Did you define your Calendar class to implement dragging destination protocol?
First off, you should use your own domain name, not “com.yourcompany”, in the UTI.
Second, did you export the UTI in your Info.plist?