Skip to content
This repository has been archived by the owner on Jan 18, 2023. It is now read-only.

Custom background redraws oddly during show/hide #29

Open
mindersw opened this issue Oct 24, 2013 · 3 comments
Open

Custom background redraws oddly during show/hide #29

mindersw opened this issue Oct 24, 2013 · 3 comments

Comments

@mindersw
Copy link

I've added the below method to PXSourceList.m to customize the background. When clicking Show/Hide on a parent row, the background has some redraw issues while collapsing or expanding. Before and after the Show/Hide operation the view is rendered fine, the problem just happens during the operation's animation.

- (void)drawBackgroundInClipRect:(NSRect)dirtyRect {

    // Added this to customize outline view background

    //// Color Declarations
    NSColor* lightColor = [NSColor colorWithCalibratedRed: 0.701 green: 0.784 blue: 0.811 alpha: 1];
    NSColor* transWhite = [NSColor colorWithCalibratedRed: 1 green: 1 blue: 1 alpha: 0.571];
    NSColor* dkGray = [NSColor colorWithCalibratedRed: 0.4 green: 0.4 blue: 0.4 alpha: 1];

    //// Gradient Declarations
    NSGradient* transWhiteGradient = [[NSGradient alloc] initWithColorsAndLocations:
                                      transWhite, 0.01,
                                      [NSColor colorWithCalibratedRed: 0.799 green: 0.913 blue: 0.95 alpha: 0.785], 0.05,
                                      lightColor, 0.37, nil];

    //// Shadow Declarations
    NSShadow* shadow = [[NSShadow alloc] init];
    [shadow setShadowColor: dkGray];
    [shadow setShadowOffset: NSMakeSize(0.1, -3.1)];
    [shadow setShadowBlurRadius: 5.5];

    //// Frames
    //NSRect dirtyRect = NSMakeRect(0, 0, 214, 727);


    //// baseRect Drawing
    NSBezierPath* baseRectPath = [NSBezierPath bezierPathWithRect: NSMakeRect(NSMinX(dirtyRect), NSMinY(dirtyRect), NSWidth(dirtyRect), NSHeight(dirtyRect))];
    [lightColor setFill];
    [baseRectPath fill];

    ////// baseRect Inner Shadow
    NSRect baseRectBorderRect = NSInsetRect([baseRectPath bounds], -shadow.shadowBlurRadius, -shadow.shadowBlurRadius);
    baseRectBorderRect = NSOffsetRect(baseRectBorderRect, -shadow.shadowOffset.width, shadow.shadowOffset.height);
    baseRectBorderRect = NSInsetRect(NSUnionRect(baseRectBorderRect, [baseRectPath bounds]), -1, -1);

    NSBezierPath* baseRectNegativePath = [NSBezierPath bezierPathWithRect: baseRectBorderRect];
    [baseRectNegativePath appendBezierPath: baseRectPath];
    [baseRectNegativePath setWindingRule: NSEvenOddWindingRule];

    [NSGraphicsContext saveGraphicsState];
    {
        NSShadow* shadowWithOffset = [shadow copy];
        CGFloat xOffset = shadowWithOffset.shadowOffset.width + round(baseRectBorderRect.size.width);
        CGFloat yOffset = shadowWithOffset.shadowOffset.height;
        shadowWithOffset.shadowOffset = NSMakeSize(xOffset + copysign(0.1, xOffset), yOffset + copysign(0.1, yOffset));
        [shadowWithOffset set];
        [[NSColor grayColor] setFill];
        [baseRectPath addClip];
        NSAffineTransform* transform = [NSAffineTransform transform];
        [transform translateXBy: -round(baseRectBorderRect.size.width) yBy: 0];
        [[transform transformBezierPath: baseRectNegativePath] fill];
    }
    [NSGraphicsContext restoreGraphicsState];

    [dkGray setStroke];
    [baseRectPath setLineWidth: 1];
    [baseRectPath stroke];


    //// topRect Drawing
    NSBezierPath* topRectPath = [NSBezierPath bezierPathWithRect: NSMakeRect(NSMinX(dirtyRect), NSMinY(dirtyRect) - 1, NSWidth(dirtyRect), NSHeight(dirtyRect) + 2)];
    [transWhiteGradient drawInBezierPath: topRectPath angle: 90];


}
@alexrozanski
Copy link
Owner

Do you have a sample project or video showing what happens?

@mindersw
Copy link
Author

Just used the attached class in place of the existing one in the example project. Note the drawBackgroundInClipRect method in the Drawing section, used to customize the background. I realize this isn't part of your release class, but I think it's important to get working correctly as people do more advanced things with their UIs.


Michael A. LaMorte
Mac Developer
Minder Softworks

On Oct 25, 2013, at 7:05 AM, Alex Rozanski notifications@github.com wrote:

Do you have a sample project or video showing what happens?


Reply to this email directly or view it on GitHub.

@alexrozanski
Copy link
Owner

It looks like the issue here is that the area you're drawing into is based on the dirtyRect parameter that is passed in. The drawing issues are occurring because this method is often called to redraw small sections of the background (which are passed in as the dirtyRect), which you're drawing into as if you were drawing the background of the entire view.

If you instead always redraw the entire background in this method then you don't get (most of) these drawing issues (as a quick test I just set dirtyRect to self.enclosingScrollView.bounds in the first line of the method). It's less efficient, but since you're working with gradients and shadows it would be tricky to do this more efficiently when only redrawing small areas.

For some reason, there is still a small flash of incorrect drawing when expanding and collapsing a section which I couldn't quite figure out. Let me know if you make progress with that.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants