Isuru
Isuru

Reputation: 31283

Custom NSLevelIndicator doesn't show assigned values

I have created a custom NSLevelIndicator which can display a string value within it. Below is the code for it. I tested this in a storyboard OSX app and it works well.

enter image description here

import Cocoa

class CustomLevelIndicator: NSLevelIndicator {

    var text: String!

    private var textField: NSTextField!

    override func drawRect(dirtyRect: NSRect) {
        super.drawRect(dirtyRect)
    }

    override func awakeFromNib() {
        textField = NSTextField()
        textField.stringValue = text
        textField.bezeled = false
        textField.drawsBackground = false
        textField.editable = false
        textField.selectable = false
        textField.textColor = NSColor.blackColor()
        textField.font = NSFont.systemFontOfSize(12)
        textField.translatesAutoresizingMaskIntoConstraints = false
        addSubview(textField, positioned: .Above, relativeTo: nil)

        let xCenterConstraint = NSLayoutConstraint(item: textField, attribute: .CenterX, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 1, constant: 0)
        let yCenterConstraint = NSLayoutConstraint(item: textField, attribute: .CenterY, relatedBy: .Equal, toItem: self, attribute: .CenterY, multiplier: 1, constant: 0)
        addConstraints([xCenterConstraint, yCenterConstraint])
    }
}

Now I'm trying to use the same control in a menu bar app. Here's the view layout of it.

enter image description here

The code of the menu object.

class ProgressMenuController: NSObject {

    @IBOutlet weak var menu: NSMenu!
    @IBOutlet weak var progressView: ProgressView!

    let menuItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)

    var progressMenuItem: NSMenuItem!

    override func awakeFromNib() {
        menuItem.menu = menu
        menuItem.image = NSImage(named: "icon")

        progressMenuItem = menu.itemWithTitle("Progress")
        progressMenuItem.view = progressView

        progressView.update(42)
    }

    @IBAction func quitClicked(sender: NSMenuItem) {
        NSApplication.sharedApplication().terminate(self)
    }
}

The code for the view that has the level indicator.

import Cocoa

class ProgressView: NSView {

    @IBOutlet weak var progressIndicator: CustomLevelIndicator!

    func update(value: Double) {
        dispatch_async(dispatch_get_main_queue()) {
            self.progressIndicator.doubleValue = value
            self.progressIndicator.text = "\(value)%"
        }
    }
}

The problem is the text in custom level indicator doesn't show up. And the level indicator has some sort of a dark overlay.

enter image description here

I can't figure out why this is happening. In my actual app, the values for this indicator is updated periodically via a network request that executes in a background thread. That's why I update the UI in the main thread specifically in the update() function. I took the code inside the closure and put it outside just to test, still it doesn't work. Note that the problem is with assigning the value for the text property and not the doubleValue as you can see the level indicator's value is updated properly but not the text. I'm kinda stumped now.

Any help is appreciated. I uploaded a demo project here as well.

Upvotes: 0

Views: 1317

Answers (2)

l'L'l
l'L'l

Reputation: 47159

The issue here seems like it might be your code is lacking an IBOutlet for the NSTextField. You could probably fix the issue by adding one that overlays your NSLevelIndicator and associating it. I didn't try your code, however, doing something as simple as the following should give you a better idea of what to do:

import Cocoa

class ProgressView: NSView {

    @IBOutlet weak var progressIndicator: CustomLevelIndicator!
    @IBOutlet weak var textValue: NSTextField!

    func update(value: Double) {
        dispatch_async(dispatch_get_main_queue()) {
            self.progressIndicator.doubleValue = value
            self.textValue.stringValue = "\(value)%"
        }
    }
}

Then just add the NSTextField on top of the NSLevelIndicator and reference ProgressView with textValue in IB; you should be in business from there.

Upvotes: 0

Willeke
Willeke

Reputation: 15589

Override the property doubleValue in CustomLevelIndicator. In the setter you set text and textField.stringValue.

Upvotes: 0

Related Questions