Search code examples
objective-ccocoansprogressindicator

What causes a white border to be applied to an NSProgressIndicator displayed in the system menu?


This is what happens when I create an NSProgressIndicator and use NSStatusItem's -setView: method to display it in the menubar area while I'm performing an action:

Example of messed up NSProgressIndicator http://cl.ly/l9R/content

What causes this border to be displayed, and how can I remove it? The intended result is that the control be transparent.

Here's the code I'm using:

NSProgressIndicator *progressIndicator = [[NSProgressIndicator alloc] init];

[progressIndicator setBezeled: NO];
[progressIndicator setStyle: NSProgressIndicatorSpinningStyle];
[progressIndicator setControlSize: NSSmallControlSize];
[progressIndicator sizeToFit];
[progressIndicator startAnimation: self];
[statusItem setView: progressIndicator]; // statusItem is an NSStatusItem instance
...
[statusItem setView: nil];
[progressIndicator stopAnimation: self];
[progressIndicator release];

Solution

  • Don’t scale the NSProgressIndicator though it’s also an NSView. Create a new view that resizes fine, position the status indicator in that view, and pass the enclosing view to -[NSStatusItem setView:]. Here is my implementation.

    In NSStatusItem+AnimatedProgressIndicator.m,

    - (void) startAnimation {
    
        NSView *progressIndicatorHolder = [[NSView alloc] init];
    
        NSProgressIndicator *progressIndicator = [[NSProgressIndicator alloc] init];
    
        [progressIndicator setBezeled: NO];
        [progressIndicator setStyle: NSProgressIndicatorSpinningStyle];
        [progressIndicator setControlSize: NSSmallControlSize];
        [progressIndicator sizeToFit];
        [progressIndicator setUsesThreadedAnimation:YES];
    
        [progressIndicatorHolder addSubview:progressIndicator];
        [progressIndicator startAnimation:self];
    
        [self setView:progressIndicatorHolder];
    
        [progressIndicator center];
    
        [progressIndicator setNextResponder:progressIndicatorHolder];
        [progressIndicatorHolder setNextResponder:self];
    
    }
    
    - (void) stopAnimation {
    
        [self setView:nil];
    
    }
    
    - (void) mouseDown:(NSEvent *) theEvent {
    
        [self popUpStatusItemMenu:[self menu]];
    
    }
    
    - (void) rightMouseUp:(NSEvent *) theEvent {}
    - (void) mouseUp:(NSEvent *) theEvent {}
    …
    

    I added a custom method, -[NSView center], which does the following:

    @implementation NSView (Centering)
    
    - (void) center {
    
        if (![self superview]) return;
    
        [self setFrame:NSMakeRect(
    
            0.5 * ([self superview].frame.size.width - self.frame.size.width),
            0.5 * ([self superview].frame.size.height - self.frame.size.height), 
    
            self.frame.size.width, 
            self.frame.size.height
    
        )];
    
    }
    
    @end