mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-15 00:34:08 +09:00
feat: added a low power mode state to the Battery popup window (#1024)
This commit is contained in:
@@ -18,6 +18,7 @@ struct Battery_Usage: value_t {
|
||||
var state: String? = nil
|
||||
var isCharged: Bool = false
|
||||
var isCharging: Bool = false
|
||||
var isLowPowerMode: Bool? = false
|
||||
var level: Double = 0
|
||||
var cycles: Int = 0
|
||||
var health: Int = 0
|
||||
@@ -137,7 +138,8 @@ public class Battery: Module {
|
||||
widget.setValue(
|
||||
percentage: value.level ,
|
||||
ACStatus: value.powerSource != "Battery Power",
|
||||
isCharging: value.isCharging ,
|
||||
isCharging: value.isCharging,
|
||||
lowPowerMode: value.isLowPowerMode,
|
||||
time: value.timeToEmpty == 0 && value.timeToCharge != 0 ? value.timeToCharge : value.timeToEmpty
|
||||
)
|
||||
default: break
|
||||
|
||||
@@ -19,7 +19,13 @@ internal class Popup: NSView, Popup_p {
|
||||
|
||||
private let dashboardHeight: CGFloat = 90
|
||||
|
||||
private let detailsHeight: CGFloat = (22 * 7) + Constants.Popup.separatorHeight
|
||||
private var detailsHeight: CGFloat {
|
||||
var count: CGFloat = 7
|
||||
if #available(macOS 12.0, *) {
|
||||
count += 1
|
||||
}
|
||||
return (22 * count) + Constants.Popup.separatorHeight
|
||||
}
|
||||
private let batteryHeight: CGFloat = (22 * 4) + Constants.Popup.separatorHeight
|
||||
private let adapterHeight: CGFloat = (22 * 2) + Constants.Popup.separatorHeight
|
||||
private let processHeight: CGFloat = (22 * 1)
|
||||
@@ -38,6 +44,7 @@ internal class Popup: NSView, Popup_p {
|
||||
private var capacityField: NSTextField? = nil
|
||||
private var cyclesField: NSTextField? = nil
|
||||
private var lastChargeField: NSTextField? = nil
|
||||
private var lowPowerModeField: NSTextField? = nil
|
||||
|
||||
private var amperageField: NSTextField? = nil
|
||||
private var voltageField: NSTextField? = nil
|
||||
@@ -76,9 +83,9 @@ internal class Popup: NSView, Popup_p {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: Constants.Popup.width,
|
||||
height: self.dashboardHeight + self.detailsHeight + self.batteryHeight + self.adapterHeight
|
||||
height: self.dashboardHeight + self.batteryHeight + self.adapterHeight
|
||||
))
|
||||
self.setFrameSize(NSSize(width: self.frame.width, height: self.frame.height+self.processesHeight))
|
||||
self.setFrameSize(NSSize(width: self.frame.width, height: self.frame.height + self.detailsHeight + self.processesHeight))
|
||||
|
||||
let gridView: NSGridView = NSGridView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height))
|
||||
gridView.rowSpacing = 0
|
||||
@@ -145,18 +152,24 @@ internal class Popup: NSView, Popup_p {
|
||||
private func initDetails() -> NSView {
|
||||
let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.detailsHeight))
|
||||
let separator = separatorView(localizedString("Details"), origin: NSPoint(x: 0, y: self.detailsHeight-Constants.Popup.separatorHeight), width: self.frame.width)
|
||||
let container: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: separator.frame.origin.y))
|
||||
|
||||
self.levelField = popupRow(container, n: 6, title: "\(localizedString("Level")):", value: "").1
|
||||
self.sourceField = popupRow(container, n: 5, title: "\(localizedString("Source")):", value: "").1
|
||||
let t = self.labelValue(container, n: 4, title: "\(localizedString("Time")):", value: "")
|
||||
let container: NSStackView = NSStackView(frame: NSRect(x: 0, y: 0, width: view.frame.width, height: separator.frame.origin.y))
|
||||
container.orientation = .vertical
|
||||
container.spacing = 0
|
||||
|
||||
self.levelField = popupRow(container, title: "\(localizedString("Level")):", value: "").1
|
||||
self.sourceField = popupRow(container, title: "\(localizedString("Source")):", value: "").1
|
||||
self.healthField = popupRow(container, title: "\(localizedString("Health")):", value: "").1
|
||||
self.capacityField = popupRow(container, title: "\(localizedString("Capacity")):", value: "").1
|
||||
self.capacityField?.toolTip = localizedString("maximum / designed")
|
||||
self.cyclesField = popupRow(container, title: "\(localizedString("Cycles")):", value: "").1
|
||||
let t = self.labelValue(container, title: "\(localizedString("Time")):", value: "")
|
||||
self.timeLabelField = t.0
|
||||
self.timeField = t.1
|
||||
self.healthField = popupRow(container, n: 3, title: "\(localizedString("Health")):", value: "").1
|
||||
self.capacityField = popupRow(container, n: 2, title: "\(localizedString("Capacity")):", value: "").1
|
||||
self.capacityField?.toolTip = localizedString("maximum / designed")
|
||||
self.cyclesField = popupRow(container, n: 1, title: "\(localizedString("Cycles")):", value: "").1
|
||||
self.lastChargeField = popupRow(container, n: 0, title: "\(localizedString("Last charge")):", value: "").1
|
||||
self.lastChargeField = popupRow(container, title: "\(localizedString("Last charge")):", value: "").1
|
||||
|
||||
if #available(macOS 12.0, *) {
|
||||
self.lowPowerModeField = popupRow(container, title: "\(localizedString("Low power mode")):", value: localizedString("Unknown")).1
|
||||
}
|
||||
|
||||
view.addSubview(separator)
|
||||
view.addSubview(container)
|
||||
@@ -215,15 +228,21 @@ internal class Popup: NSView, Popup_p {
|
||||
return view
|
||||
}
|
||||
|
||||
private func labelValue(_ view: NSView, n: CGFloat, title: String, value: String) -> (NSTextField, NSTextField) {
|
||||
let rowView: NSView = NSView(frame: NSRect(x: 0, y: 22*n, width: view.frame.width, height: 22))
|
||||
private func labelValue(_ view: NSView, title: String, value: String) -> (NSTextField, NSTextField) {
|
||||
let rowView: NSView = NSView(frame: NSRect(x: 0, y: 0, width: view.frame.width, height: 22))
|
||||
|
||||
let labelView: LabelField = LabelField(frame: NSRect(x: 0, y: (22-15)/2, width: view.frame.width/2, height: 15), title)
|
||||
let valueView: ValueField = ValueField(frame: NSRect(x: view.frame.width/2, y: (22-16)/2, width: view.frame.width/2, height: 16), value)
|
||||
|
||||
rowView.addSubview(labelView)
|
||||
rowView.addSubview(valueView)
|
||||
view.addSubview(rowView)
|
||||
|
||||
if let view = view as? NSStackView {
|
||||
rowView.heightAnchor.constraint(equalToConstant: rowView.bounds.height).isActive = true
|
||||
view.addArrangedSubview(rowView)
|
||||
} else {
|
||||
view.addSubview(rowView)
|
||||
}
|
||||
|
||||
return (labelView, valueView)
|
||||
}
|
||||
@@ -289,6 +308,10 @@ internal class Popup: NSView, Popup_p {
|
||||
self.lastChargeField?.toolTip = localizedString("Unknown")
|
||||
}
|
||||
|
||||
if let powerMode = value.isLowPowerMode {
|
||||
self.lowPowerModeField?.stringValue = powerMode ? localizedString("Enabled") : localizedString("Disabled")
|
||||
}
|
||||
|
||||
self.amperageField?.stringValue = "\(abs(value.amperage)) mA"
|
||||
self.voltageField?.stringValue = "\(value.voltage.roundTo(decimalPlaces: 2)) V"
|
||||
let batteryPower = value.voltage * (Double(abs(value.amperage))/1000)
|
||||
|
||||
@@ -39,6 +39,10 @@ internal class UsageReader: Reader<Battery_Usage> {
|
||||
CFRunLoopAddSource(self.loop, source, .defaultMode)
|
||||
|
||||
self.read()
|
||||
|
||||
if #available(macOS 12.0, *) {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(self.lowModeChanged), name: Notification.Name.NSProcessInfoPowerStateDidChange, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
public override func stop() {
|
||||
@@ -50,6 +54,10 @@ internal class UsageReader: Reader<Battery_Usage> {
|
||||
CFRunLoopRemoveSource(runLoop, source, .defaultMode)
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
public override func read() {
|
||||
let psInfo = IOPSCopyPowerSourcesInfo().takeRetainedValue()
|
||||
let psList = IOPSCopyPowerSourcesList(psInfo).takeRetainedValue() as [CFTypeRef]
|
||||
@@ -63,6 +71,9 @@ internal class UsageReader: Reader<Battery_Usage> {
|
||||
self.usage.powerSource = list[kIOPSPowerSourceStateKey] as? String ?? "AC Power"
|
||||
self.usage.isCharged = list[kIOPSIsChargedKey] as? Bool ?? false
|
||||
self.usage.isCharging = self.getBoolValue("IsCharging" as CFString) ?? false
|
||||
if #available(macOS 12.0, *) {
|
||||
self.usage.isLowPowerMode = ProcessInfo.processInfo.isLowPowerModeEnabled
|
||||
}
|
||||
self.usage.level = Double(list[kIOPSCurrentCapacityKey] as? Int ?? 0) / 100
|
||||
|
||||
if let time = list[kIOPSTimeToEmptyKey] as? Int {
|
||||
@@ -139,6 +150,13 @@ internal class UsageReader: Reader<Battery_Usage> {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@objc private func lowModeChanged() {
|
||||
if #available(macOS 12.0, *) {
|
||||
self.usage.isLowPowerMode = ProcessInfo.processInfo.isLowPowerModeEnabled
|
||||
self.callback(self.usage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcessReader: Reader<[TopProcess]> {
|
||||
|
||||
Reference in New Issue
Block a user