cocoanstextfieldnstextfieldcell

How to achieve the recessed text style as in Apple's Messages for Mac?


I'd like to replicate the recessed text style of Messages/iMessage, or, the text "white-shadow" style on a light gray background.

example

As you can see, the texts are with "white-shadow" even on the light gray background. The bold texts do have subpixel rendering while the gray texts don't (by design?).

I've tried -setBackgroundStyle:NSBackgroundStyleRaised . However it was generating shadows darker than the background. -setBackgroundStyle:NSBackgroundStyleLowered was worse that it even overrode my font colour setting.

So, what is the right way to do this? Any tricks or just have to subclass NSTextFields?


Solution

  • Solution 1:

    The most simplest solution which I can think is to write two texts on each other (For example gray on top and white with difference 1px at bottom).


    Solution 2:

    And of course it can be done by subclassing NSTextFieldCell and adding shadow.

    Just like this:

    - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
    {
        NSShadow *shadow = [[NSShadow alloc] init];
        [shadow setShadowOffset:NSMakeSize(0,-1)];
        [shadow setShadowColor:[NSColor whiteColor]];
        [shadow setShadowBlurRadius:0];
    
        NSMutableParagraphStyle *paragStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
        [paragStyle setAlignment:[self alignment]];
    
        NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                          [self font],NSFontAttributeName,
                          shadow,NSShadowAttributeName,
                          [self textColor],NSForegroundColorAttributeName,
                          paragStyle,NSParagraphStyleAttributeName,nil];
        [shadow release];
        [paragStyle release];
    
        NSAttributedString *string = [[NSAttributedString alloc] initWithString:[self stringValue] attributes:attributes];
        [self setAttributedStringValue:string];
        [string release];
        [[self attributedStringValue] drawInRect:cellFrame];
    }
    

    Result:

    Text example