From 2ea195de1e5ae24c3c12aa78ff3e115a6307dbfd Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Mon, 17 Jun 2019 15:29:18 +0200 Subject: [PATCH] added percentage to battery module --- README.md | 2 +- Stats/Modules/Battery/Battery.swift | 29 +++++++++++++++ Stats/Widgets/BatteryView.swift | 58 +++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ff68cdf4..fdf867cd 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ You can download latest version [here](https://github.com/exelban/stats/releases | **CPU** | Percentage / Chart / Chart with value | Shows CPU usage | | **Memory** | Percentage / Chart / Chart with value | Shows RAM usage | | **Disk** | Percentage | Shows disk filling | -| **Battery** | Graphic | Shows battery level and charging status | +| **Battery** | Graphic / Percentage | Shows battery level and charging status | ## Compatibility | macOS | Compatible | diff --git a/Stats/Modules/Battery/Battery.swift b/Stats/Modules/Battery/Battery.swift index d57555c0..6d78bb4d 100644 --- a/Stats/Modules/Battery/Battery.swift +++ b/Stats/Modules/Battery/Battery.swift @@ -20,12 +20,15 @@ class Battery: Module { let defaults = UserDefaults.standard var widgetType: WidgetType = Widgets.Mini + let percentageView: Observable init() { self.available = Observable(self.reader.available) self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true) + self.percentageView = Observable(defaults.object(forKey: "\(self.name)_percentage") != nil ? defaults.bool(forKey: "\(self.name)_percentage") : false) self.view = BatteryView(frame: NSMakeRect(0, 0, MODULE_WIDTH, MODULE_HEIGHT)) initMenu() + initWidget() } func start() { @@ -44,8 +47,16 @@ class Battery: Module { } } + func initWidget() { + self.active << false + (self.view as! BatteryView).setPercentage(value: self.percentageView.value) + self.active << true + } + func initMenu() { menu = NSMenuItem(title: name, action: #selector(toggle), keyEquivalent: "") + submenu = NSMenu() + if defaults.object(forKey: name) != nil { menu.state = defaults.bool(forKey: name) ? NSControl.StateValue.on : NSControl.StateValue.off } else { @@ -53,6 +64,13 @@ class Battery: Module { } menu.target = self menu.isEnabled = true + + let percentage = NSMenuItem(title: "Percentage", action: #selector(togglePercentage), keyEquivalent: "") + percentage.state = defaults.bool(forKey: "\(self.name)_percentage") ? NSControl.StateValue.on : NSControl.StateValue.off + percentage.target = self + + submenu.addItem(percentage) + menu.submenu = submenu } @objc func toggle(_ sender: NSMenuItem) { @@ -63,10 +81,21 @@ class Battery: Module { self.active << state if !state { + menu.submenu = nil self.stop() } else { + menu.submenu = submenu self.start() } } + + @objc func togglePercentage(_ sender: NSMenuItem) { + let state = sender.state != NSControl.StateValue.on + + sender.state = sender.state == NSControl.StateValue.on ? NSControl.StateValue.off : NSControl.StateValue.on + self.defaults.set(state, forKey: "\(self.name)_percentage") + self.percentageView << state + self.initWidget() + } } diff --git a/Stats/Widgets/BatteryView.swift b/Stats/Widgets/BatteryView.swift index 4b1dbef5..535c3c55 100644 --- a/Stats/Widgets/BatteryView.swift +++ b/Stats/Widgets/BatteryView.swift @@ -9,6 +9,9 @@ import Cocoa class BatteryView: NSView, Widget { + let batteryWidth: CGFloat = 32 + let percentageWidth: CGFloat = 40 + var value: Float { didSet { self.redraw() @@ -19,13 +22,21 @@ class BatteryView: NSView, Widget { self.redraw() } } + var percentage: Bool { + didSet { + self.redraw() + } + } + + var percentageValue: NSTextField = NSTextField() override init(frame: NSRect) { self.value = 1.0 self.charging = false + self.percentage = false super.init(frame: frame) self.wantsLayer = true - self.addSubview(NSView()) + self.percentageView() } required init?(coder decoder: NSCoder) { @@ -35,11 +46,15 @@ class BatteryView: NSView, Widget { override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) - let x: CGFloat = 4.0 - let w: CGFloat = dirtyRect.size.width - (x * 2) + var x: CGFloat = 4.0 + var w: CGFloat = dirtyRect.size.width - (x * 2) let h: CGFloat = 11.0 let y: CGFloat = (dirtyRect.size.height - h) / 2 let r: CGFloat = 1.0 + if self.percentage { + w = batteryWidth - (x * 2) + x = percentageWidth + x + } let battery = NSBezierPath(roundedRect: NSRect(x: x-1, y: y, width: w-1, height: h), xRadius: r, yRadius: r) @@ -72,6 +87,32 @@ class BatteryView: NSView, Widget { battery.stroke() } + func percentageView() { + if self.percentage { + percentageValue = NSTextField(frame: NSMakeRect(0, 0, percentageWidth, self.frame.size.height - 2)) + percentageValue.textColor = NSColor.red + percentageValue.isEditable = false + percentageValue.isSelectable = false + percentageValue.isBezeled = false + percentageValue.wantsLayer = true + percentageValue.textColor = .labelColor + percentageValue.backgroundColor = .controlColor + percentageValue.canDrawSubviewsIntoLayer = true + percentageValue.alignment = .natural + percentageValue.font = NSFont.systemFont(ofSize: 13, weight: .light) + percentageValue.stringValue = "\(Int(self.value * 100))%" + + self.addSubview(percentageValue) + self.frame = CGRect(x: 0, y: 0, width: batteryWidth + percentageWidth, height: self.frame.size.height) + } else { + for subview in self.subviews { + subview.removeFromSuperview() + } + self.addSubview(NSView()) + self.frame = CGRect(x: 0, y: 0, width: batteryWidth, height: self.frame.size.height) + } + } + func redraw() { self.needsDisplay = true setNeedsDisplay(self.frame) @@ -80,6 +121,10 @@ class BatteryView: NSView, Widget { func value(value: Float) { if self.value != value { self.value = value + + if percentage { + self.percentageValue.stringValue = "\(Int(self.value * 100))%" + } } } @@ -88,4 +133,11 @@ class BatteryView: NSView, Widget { self.charging = value } } + + func setPercentage(value: Bool) { + if self.percentage != value { + self.percentage = value + self.percentageView() + } + } }