How to stop the animation on a determinate NSProgressIndicator?

1.6k views Asked by At

NSProgressIndicator allows stopAnimation: when isIndeterminate == YES, but how does one stop the animation for determinate progress bars?

For context, the progress bar I am trying to do this with is a child of an NSView, which itself is the view property of an NSMenuItem. Sending ridiculously high numbers to setAnimationDelay: does what I want, but only temporarily -- when the parent menu is closed and re-opened, the progress bar is animated again.

(Possibly unnecessary disclaimer: I swear this is a legit use case; I have to be able to visually (i.e.: without using text) display the progress of very-long-running tasks which may pause and re-start as needed by the backend. Answers which boil down to "UI design: ur doin it rong" will be not be accepted unless accompanied by a brilliant alternative suggestion. ;) )

2

There are 2 answers

2
jensck On

Solved the problem using the same approach as described previously, with one small change.

When the menu's delegate receives menuNeedsUpdate:, I send setAnimationDelay: (with the sufficiently huge number as the arg) to each progress bar. This is working reliably now, so I'm happy enough with it.

2
BeBa On

Subclass NSProgressIndicator like this, it also works with Lion:

@interface UnanimatedProgressIndicator : NSProgressIndicator {
@private
    BOOL    isAnimating;
}
@end

@interface NSProgressIndicator (HeartBeat)
- (void) heartBeat:(id)sender;      // Apple internal method for the animation
@end

@implementation UnanimatedProgressIndicator

- (void) startAnimation:(id)sender
{
    isAnimating = YES;
    [super startAnimation:sender];
}

- (void) stopAnimation:(id)sender
{
    isAnimating = NO;
    [super stopAnimation:sender];
}

- (void) heartBeat:(id)sender
{
    if (isAnimating)
        [super heartBeat:sender];
}

@end