Subclass NSProgressIndicator

i like to subclass a NSProgressIndicator. I've used this code and i set the Subclass in the Interface Builder:

- (void)drawRect:(NSRect)dirtyRect {
NSRect rect = NSInsetRect([self bounds], 1.0, 1.0);
CGFloat radius = rect.size.height / 2;
NSBezierPath *bz = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius];
[bz setLineWidth:2.0];
[[NSColor blackColor] set];
[bz stroke];

rect = NSInsetRect(rect, 2.0, 2.0);
radius = rect.size.height / 2;
bz = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius];
[bz setLineWidth:1.0];
[bz addClip];
rect.size.width = floor(rect.size.width * ([self doubleValue] / [self maxValue]));
NSRectFill(rect);

When the app starts its looks like this: App start

But during the copy progress the old bar shows up. During copying

Whats wrong?


ANSWERS:


It seems that the progress bar's progress is not drawn in drawRect:, so just overriding drawRect: is not enough. However, if you make the progress bar layer backed, you are responsible for doing all the drawing.

From the documentation:

The view class automatically creates a backing layer for you (using makeBackingLayer if overridden), and you must use the view class’s drawing mechanisms.

Check the "Core Animation Layer" in IB or add this to your sub class:

- (void)awakeFromNib {
    [super awakeFromNib];
    [self setWantsLayer:YES];
}

I followed the above advice (thanks!), but unfortunately discovered that when the NSProgressIndicator was resized, it disappeared, but only on the first viewing (it was inside a drawer).

Rather than try and understand what was happening, I realised you don't actually need the old control, as what I was doing is very simple (a strength indicator that changes color). Just create a subclass of NSView.

So this is it:

@interface SSStrengthIndicator : NSView
/// Set the indicator based upon a score from 0..4
@property (nonatomic) double strengthScore;
@end

@implementation SSStrengthIndicator
- (void)setStrengthScore:(double)strength
{
    if (_strengthScore != strength) {
        _strengthScore = strength;
        [self setNeedsDisplay:YES];
   }
}

- (void)drawRect:(NSRect)dirtyRect
{
    NSRect rect = NSInsetRect([self bounds], 1.0, 2.0);
    double  val = (_strengthScore + 1) * 20;
    if (val <= 40)
        [[NSColor redColor] set];
    else if (val <= 60)
        [[NSColor yellowColor] set];
    else
        [[NSColor greenColor] set];

    rect.size.width = floor(rect.size.width * (val / 100.0));
    [NSBezierPath fillRect:rect];
}
@end


 MORE:


 ? Resume NSProgressIndicator animation after window minimised and then restored
 ? How do I open a .dmg file from my code?
 ? How to change NSPopover background color include triangle part?
 ? How to change NSPopover background color include triangle part?
 ? How to change NSPopover background color include triangle part?
 ? How to change NSPopover background color include triangle part?
 ? NSPopover color invert in Yosemite dark color
 ? NSPopover color
 ? Would like to change the opacity for an NSPopover - is it possible?
 ? NSProgressIndicator can't set background color to white