Reputation: 31283
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.
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.
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.
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
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
Reputation: 15589
Override the property doubleValue in CustomLevelIndicator. In the setter you set text and textField.stringValue.
Upvotes: 0