I started using objective-c today in order to develop an app for OSX (mountain lion). I have a bunch of buttons that I would like to drag them into some other object, for instance a text field. I followed the tutorials on apple's dev site, but I wans't able to get the drag part working (the drop part works, for instance, I can drag a file from finder into a text file and show its path).
I started by creating a NSButton subclass:
@interface mp3OCDDraggableButton : NSButton
and implemented the methods as described in: https://developer.apple.com/library/mac/#samplecode/CocoaDragAndDrop/Introduction/Intro.html
but the thing doest move!
I put some log messages in mouseDown:, which I can see in, but not if I replace it by mouseDragged: - does this tells me anything?
Can anyone post a simple example with this functionality? I couldn't find anything that works :\
many thanks in advance!
This is the code I have so far for the draggable button. Pretty much the same as in the tutorial.
//myDraggableButton.h
@interface myDraggableButton : NSButton <NSDraggingSource, NSPasteboardItemDataProvider>
@end
and
//myDraggableButton.m
#import "myDraggableButton.h"
@implementation myDraggableButton
- (void)mouseDown:(NSEvent *)theEvent:(NSEvent*)event
{
NSLog(@"mouseDown");
NSPasteboardItem *pbItem = [NSPasteboardItem new];
[pbItem setDataProvider:self forTypes:[NSArray arrayWithObjects:NSPasteboardTypeString, nil]];
NSDraggingItem *dragItem = [[NSDraggingItem alloc] initWithPasteboardWriter:pbItem];
NSRect draggingRect = self.bounds;
[dragItem setDraggingFrame:draggingRect contents:[self image]];
NSDraggingSession *draggingSession = [self beginDraggingSessionWithItems:[NSArray arrayWithObject:dragItem] event:event source:self];
draggingSession.animatesToStartingPositionsOnCancelOrFail = YES;
draggingSession.draggingFormation = NSDraggingFormationNone;
}
- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{
switch (context) {
case NSDraggingContextOutsideApplication:
return NSDragOperationCopy;
case NSDraggingContextWithinApplication:
default:
return NSDragOperationCopy;
break;
}
}
- (BOOL)acceptsFirstMouse:(NSEvent *)event
{
return YES;
}
- (void)pasteboard:(NSPasteboard *)sender item:(NSPasteboardItem *)item provideDataForType:(NSString *)type
{
if ( [type compare: NSPasteboardTypeTIFF] == NSOrderedSame ) {
[sender setData:[[self image] TIFFRepresentation] forType:NSPasteboardTypeTIFF];
} else if ( [type compare: NSPasteboardTypePDF] == NSOrderedSame ) {
[sender setData:[self dataWithPDFInsideRect:[self bounds]] forType:NSPasteboardTypePDF];
}
}
@end
I apologize for the necromancy, but I stumbled across this question while trying to implement this myself and would like to share the answer because it might be useful to others.
This solution uses categories on
NSActionCell
andNSControl
because I needed to be able to drag multiple control types, not just buttons. You can adapt this to your needs/classes.I have commented out code relating to a workaround hack for an undesired fade animation when hiding/unhiding the controls. I fiddled with implicit animations and the like, but couldnt figure out a better way. The hack does work nicely, but I left the window implementation code out.
Could the problem be that you're calling
-setDataProvider:forTypes:
withNSPasteboardTypeString
but your-pasteboard:item:provideDataForType:
does nothing when passed that type?