Strange drawing behavior of NSSegmentedControl, when superview is drawn

514 views Asked by At

I've got a problem with the NSSegmentedControl. I have a custom view where I draw a gradient with a shadow. The drawing is ok, but when I place a NSSegmentedControl inside it then something strange happens - the background of the custom view is shining through the segmented control, as if the segmented control had a low alpha value.

Here are pictures, that demonstrate the issue :

With the custom view in background : enter image description here

Without the custom view in background : enter image description here

As you can see in the left upper corner in the first image the segmented control isn't drawing properly. Here is the drawRect method from the custom view :

- (void)drawRect:(NSRect)dirtyRect {

    NSShadow *shadow = [[NSShadow alloc] init];

    [shadow setShadowOffset:NSMakeSize(0.0, -6.0)];

    [shadow setShadowBlurRadius:3.0];

    [shadow setShadowColor:[[NSColor blackColor] colorWithAlphaComponent:0.3]];

    [shadow set];



    NSGradient *gradient = [[NSGradient alloc] initWithColorsAndLocations:[NSColor colorWithDeviceWhite:0.8 alpha:1.0],(CGFloat)0.0,[NSColor colorWithDeviceWhite:0.65 alpha:1.0],(CGFloat)0.5,[NSColor colorWithDeviceWhite:0.3 alpha:1.0],(CGFloat)0.5,[NSColor colorWithDeviceWhite:0.5 alpha:1.0],(CGFloat)1.0, nil];

    [gradient drawInRect:self.bounds angle:90];



    NSBezierPath *bezierPath = [NSBezierPath bezierPath];

    [bezierPath moveToPoint:NSMakePoint(0, 0)];

    [bezierPath lineToPoint:NSMakePoint(-self.bounds.size.height, 0)];

    [bezierPath lineToPoint:NSMakePoint(-self.bounds.size.height, -self.bounds.size.width)];

    [bezierPath lineToPoint:NSMakePoint(0, -self.bounds.size.width)];



    [[NSColor whiteColor] set];



    [bezierPath stroke];

}    

Can you help me with this? I don't know how to fix this issue.

2

There are 2 answers

0
Ryan Nichols On

I don't know if you're doing any custom drawing in the toolbar buttons, but I think your problem is that you're calling 'set' on the shadow without saving and restoring your graphics context.

Look at the documentation for NSShadow's set method. NSShadow Documentation

"The shadow attributes of the receiver are used until another shadow is set or until the graphics state is restored."

You should always save your graphics context first, then call any of Cocoa's set-style methods, then restore the context. This keeps future draw commands from applying your shadow.

NSGraphicsContext *context = [NSGraphicsContext currentContext];
[context saveGraphicsState];

NSShadow *myCoolShadow = [NSShadow new];
// Shadow code here
[myCoolShadow set];

[context restoreGraphicsState];
0
Aditya Vaidyam On

On 10.7+, Rounded Textured segmented controls and buttons are transparent. On 10.5-10.6, they are gradient filled.