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

Tuesday, August 21, 2007

Picking up PageSetup Dialog Changes

The standard Page Setup dialog (OK, "sheet") can be customized by implementing -runPageLayout in your NSApplication or NSDocument subclass. It's all nicely documented in Apple's fine Developer Docs.

But what if the standard dialog is fine for your needs but you still want to run some code when the user changes the page setup?

All you need to do is implement -setPrintInfo in your NSDocument subclass. It'll get called with the new printInfo. Something like this:

- (void) setPrintInfo:(NSPrintInfo*)info
{
[super setPrintInfo:info];
[self myCodeThatDoesSomethingWithTheNewPrintInfo];
}