|
final class AssociatedObject<T: Any> { |
|
subscript(index: Any) -> T? { |
|
get { |
|
return objc_getAssociatedObject(index, Unmanaged.passUnretained(self).toOpaque()) as! T? |
|
} set { |
|
objc_setAssociatedObject(index, Unmanaged.passUnretained(self).toOpaque(), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) |
|
} |
|
} |
|
} |
|
|
|
extension NSStatusBar { |
|
static func statusItem(withLength length: CGFloat = NSSquareStatusItemLength) -> NSStatusItem { |
|
return system().statusItem(withLength: length) |
|
} |
|
} |
|
|
|
extension NSStatusBarButton { |
|
private struct AssociatedKeys { |
|
static var statusItemHolder = AssociatedObject<NSStatusItem>() |
|
} |
|
|
|
var statusBar: NSStatusBar { |
|
return NSStatusBar.system() |
|
} |
|
|
|
var length: CGFloat { |
|
get { |
|
return statusItem.length |
|
} |
|
set { |
|
statusItem.length = newValue |
|
} |
|
} |
|
|
|
override open var menu: NSMenu? { |
|
get { |
|
return statusItem.menu |
|
} |
|
set { |
|
statusItem.menu = newValue |
|
} |
|
} |
|
|
|
var statusItem: NSStatusItem { |
|
get { |
|
return AssociatedKeys.statusItemHolder[self]! |
|
} |
|
set { |
|
AssociatedKeys.statusItemHolder[self] = newValue |
|
} |
|
} |
|
} |
|
|
|
/// Creates a NSStatusBarButton with proxy methods for the NSStatusItem methods, so you don't have to deal with that class anymore. Most of the NSStatusItem properties are deprecated, so it's much nicer to deal with the NSStatusBarButton directly. |
|
func StatusBarButton() -> NSStatusBarButton { |
|
let statusItem = NSStatusBar.statusItem() |
|
statusItem.isVisible = true |
|
statusItem.behavior = [.removalAllowed, .terminationOnRemoval] |
|
let button = statusItem.button! |
|
button.statusItem = statusItem |
|
return button |
|
} |
|
|
|
func main() { |
|
let statusBarButton = StatusBarButton() |
|
statusBarButton.menu = NSMenu() |
|
statusBarButton.image = #imageLiteral(resourceName: "menubar-icon") |
|
} |
That is butchering :)