8
votes

I have an NSText field in MainMenu.xib and I have an action set to validate it for an email address. I want the NSTexFields border color (That blue glow) to be red when my action returns NO and green when the action returns YES. Here is the action:

-(BOOL) validEmail:(NSString*) emailString {
    NSString *regExPattern = @"^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$";
    NSRegularExpression *regEx = [[NSRegularExpression alloc] initWithPattern:regExPattern     options:NSRegularExpressionCaseInsensitive error:nil];
    NSUInteger regExMatches = [regEx numberOfMatchesInString:emailString options:0 range:NSMakeRange(0, [emailString length])];
    NSLog(@"%ld", regExMatches);
    if (regExMatches == 0) {
        return NO;
    } else
        return YES;
}  

I call this function and setting the text-color right now, but I would like to set the NSTextField's glow color instead.

- (void) controlTextDidChange:(NSNotification *)obj{
    if ([obj object] == emailS) {
        if ([self validEmail:[[obj object] stringValue]]) {
            [[obj object] setTextColor:[NSColor colorWithSRGBRed:0 green:.59 blue:0 alpha:1.0]];
            [reviewButton setEnabled:YES];
        } else {
            [[obj object] setTextColor:[NSColor colorWithSRGBRed:.59 green:0 blue:0 alpha:1.0]];
            [reviewButton setEnabled:NO];
        }
    }
}

I am open to sub-classing NSTextField, but the cleanest way to do this would be greatly appreciated!

2
Did you ever figure this out? I was looking for the same thing. I don't know if there is a standard way to indicate an invalid field in Cocoa.Rob N

2 Answers

4
votes

My solution for Swift 2 is


    @IBOutlet weak var textField: NSTextField!

...

// === set border to red ===
// if text field focused right now
NSApplication.sharedApplication().mainWindow?.makeFirstResponder(self)
// disable following focusing
textField.focusRingType = .None
// enable layer
textField.wantsLayer = true
// change border color
textField.layer?.borderColor = NSColor.redColor().CGColor
// set border width
textField.layer?.borderWidth = 1

0
votes

The way to go about this is to subclass NSTextFieldCell and draw your own focus ring. As far as I can tell there's no way to tell the system to draw the focus ring using your own color, so you'll have to call setFocusRingType:NSFocusRingTypeNone, check if the control has first responder status in your drawing method, and if so draw a focus ring using your own color.

If you decide to use this approach remember that the focus ring is a user defined style (blue or graphite), and there's no guarantee future versions of OSX won't allow the user to change the standard color to red or green. It's also likely the focus ring drawing style will change in future versions of OSX, at which point you'll have to update your drawing code in order for things to look right.