Tuesday, August 28, 2007

NSImageView and image filenames

One of my pet peeves with the cocoa class NSImageView is that there is no way to directly get the path of image files you drop on this view.

Below is my cure for this. It overrides two methods to do its work.

First it overrides -performDragOperation to grab the filename from the draggingPasteboard, squirreling it away in an ivar for later access.

This may be sufficient for many uses, especially if you can easily access the view from you code. In my last use of this code, I was using bindings, so I wanted the filename to be available to me when -observeValueForKeyPath was called with a keyPath of "selection.image". I didn't have any reference to the NSImageView at that point, so I have the code set the image's name to be the path string. That makes it easy enough to access the image's name later when needed.

Note: this code sets the image's name in the -setImage method because trying to set the name of the view's image inside -performDragOperation results in setting the name for the old image (the one being replaced), rather than the new one.

@interface MyImageView : NSImageView
{
NSString *mImagename;
}
@end

@implementation MyImageView

- (void)setImage:(NSImage *)image
{
[image setName:[[mImagename lastPathComponent] stringByDeletingPathExtension]];
[super setImage:image];
}

- (BOOL)performDragOperation:(id )sender
{
BOOL dragSucceeded = [super performDragOperation:sender];
if (dragSucceeded) {
NSString *filenamesXML = [[sender draggingPasteboard] stringForType:NSFilenamesPboardType];
if (filenamesXML) {
NSArray *filenames = [NSPropertyListSerialization
propertyListFromData:[filenamesXML dataUsingEncoding:NSUTF8StringEncoding]
mutabilityOption:NSPropertyListImmutable
format:nil
errorDescription:nil];
if ([filenames count] >= 1) {
mImagename = [filenames objectAtIndex:0];
} else {
mImagename = nil;
}
}
}
return dragSucceeded;
}

@end

No comments: