views:

191

answers:

1

I would like to solicit additional information from the user during the NSOpenPanel but need to validate that information before the open panel completes. For example, I may want to allow the user to add a note about the file in the open panel selection but need to validate that that comment is not empty.

I have an accessory view whose controls are bound to an NSObjectController whose content object in turn is bound to the represented object of the NSViewController that I use to load the accessory view's nib. The represented object has NSKeyValueCoding-compliant validation methods (e.g. -(BOOL)validateKey:error:). Validation is correctly handled (and violations reported via modal dialog) when the user modifies the values of the controls.

My problem is that I can't figure out how to get validation if the user doesn't enter anything in the accessory view. For example, say I have a single text field in the accessory view whose bound object validates that the text is non-zero in length. If the user enters text (validation succeeds), then deletes the text, validation fails and the user is presented with the error. However, if the user doesn't enter text, the open panel dismisses without error. How can I validate that the text is non-zero before the open panel dismisses?

+1  A: 

You should register your controller as the open panel's delegate and then implement the -panel:isValidFilename: delegate method. Returning NO from that method allows you to prevent the open dialog from being closed:

- (BOOL)panel:(id)sender isValidFilename:(NSString *)filename
{
    //validate the field in some way, in this case by making sure it's not empty
    if([[textField stringValue] length] == 0)
    {
        //let the user know they need to do something
        NSAlert *alert = [[NSAlert alloc] init];
        [alert setMessageText:@"Please enter some text."];
        [alert addButtonWithTitle:@"OK"];
        [alert beginSheetModalForWindow:sender modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
        //return NO to prevent the open panel from completing
        return NO;
    }
    //otherwise, allow the open panel to close
    return YES;
}
Rob Keniger