4
votes

I wrote my own NSMenu like class to show dynamic search results below a NSSearchField in a borderless NSWindow. It's working well but doesn't draw the magic selectedMenuItemColor correctly if I add some padding to the top of the subview. I put a 5 pixel padding at the top of container view to mimic NSMenu and when I do it blue selected gradient looks off. A picture & code should make this clear:

enter image description here

Here is my drawRect code inside my item view (remember this is just a regular NSView):

-(void) drawRect:(NSRect)dirtyRect {
    CGRect b = self.bounds;
    if (selected) {

        [NSGraphicsContext saveGraphicsState];

        [[NSColor selectedMenuItemColor] set];
        NSRectFill( b );

        [NSGraphicsContext restoreGraphicsState];
        if (textField) {
            textField.textColor = [NSColor selectedMenuItemTextColor];
        }
    } else {
        [[NSColor clearColor] set];
       NSRectFillUsingOperation(b, NSCompositeSourceOver);
        if (textField) {
            textField.textColor = [NSColor blackColor];
        }
    }
}
1
When I try to use selectedMenuItemColor, I only get the dark blue background and not the lighter gradient on top of it as is shown in your screenshot. Did you have to do anything special to get that to show up?jtbandes
No I didn't. Want to paste a gist that I can take a look at?John Wright

1 Answers

0
votes

You have to get the pattern phase origin to match your view frame.

That is, selectedMenuItemColor is actually a pattern, not a color, and that pattern is designed to display "properly" in "standard menu item height" increments. Because you have added the padding, now it is not being drawn at the "standard" location.

Try this:

-(void) drawRect:(NSRect)dirtyRect {
    CGRect b = self.bounds;
    if (selected) {

       NSPoint origin = [self frame].origin;
       curContext = [NSGraphicsContext currentContext];
       [curContext saveGraphicsState];
       [curContext setPatternPhase: origin];

        [[NSColor selectedMenuItemColor] set];
        NSRectFill( b );

        [curContext restoreGraphicsState];
        if (textField) {
            textField.textColor = [NSColor selectedMenuItemTextColor];
        }
    } else {
        [[NSColor clearColor] set];
       NSRectFillUsingOperation(b, NSCompositeSourceOver);
        if (textField) {
            textField.textColor = [NSColor blackColor];
        }
    }
}