mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
moved view to file
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
9A09C89E22B3A7C90018426F /* Battery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A09C89D22B3A7C90018426F /* Battery.swift */; };
|
||||
9A09C8A022B3A7E20018426F /* BatteryReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A09C89F22B3A7E20018426F /* BatteryReader.swift */; };
|
||||
9A09C8A222B3D94D0018426F /* BatteryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A09C8A122B3D94D0018426F /* BatteryView.swift */; };
|
||||
9A1410F9229E721100D29793 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1410F8229E721100D29793 /* AppDelegate.swift */; };
|
||||
9A141100229E721200D29793 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9A1410FE229E721200D29793 /* Main.storyboard */; };
|
||||
9A57A18522A1D26D0033E318 /* MenuBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A57A18422A1D26D0033E318 /* MenuBar.swift */; };
|
||||
@@ -48,6 +49,7 @@
|
||||
/* Begin PBXFileReference section */
|
||||
9A09C89D22B3A7C90018426F /* Battery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Battery.swift; sourceTree = "<group>"; };
|
||||
9A09C89F22B3A7E20018426F /* BatteryReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryReader.swift; sourceTree = "<group>"; };
|
||||
9A09C8A122B3D94D0018426F /* BatteryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryView.swift; sourceTree = "<group>"; };
|
||||
9A1410F5229E721100D29793 /* Stats.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Stats.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9A1410F8229E721100D29793 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
9A1410FF229E721200D29793 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
@@ -99,6 +101,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9A09C89D22B3A7C90018426F /* Battery.swift */,
|
||||
9A09C8A122B3D94D0018426F /* BatteryView.swift */,
|
||||
9A09C89F22B3A7E20018426F /* BatteryReader.swift */,
|
||||
);
|
||||
path = Battery;
|
||||
@@ -322,6 +325,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9A09C8A222B3D94D0018426F /* BatteryView.swift in Sources */,
|
||||
9A7B8F6F22A2C57000DEB352 /* DiskReader.swift in Sources */,
|
||||
9A7B8F6922A2C3A100DEB352 /* Memory.swift in Sources */,
|
||||
9A7B8F5E22A2A57600DEB352 /* CPUReader.swift in Sources */,
|
||||
|
||||
@@ -8,85 +8,6 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
class BatteryView: NSView {
|
||||
var value: Float {
|
||||
didSet {
|
||||
self.needsDisplay = true
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
}
|
||||
var charging: Bool {
|
||||
didSet {
|
||||
self.needsDisplay = true
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
}
|
||||
|
||||
override init(frame: NSRect) {
|
||||
self.value = 1.0
|
||||
self.charging = false
|
||||
super.init(frame: frame)
|
||||
self.wantsLayer = true
|
||||
self.addSubview(NSView())
|
||||
}
|
||||
|
||||
required init?(coder decoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
super.draw(dirtyRect)
|
||||
|
||||
let x: CGFloat = 4.0
|
||||
let 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
|
||||
|
||||
let battery = NSBezierPath(roundedRect: NSRect(x: x-1, y: y, width: w-1, height: h), xRadius: r, yRadius: r)
|
||||
|
||||
let bPX: CGFloat = x+w-2
|
||||
let bPY: CGFloat = (dirtyRect.size.height / 2) - 2
|
||||
let batteryPoint = NSBezierPath(roundedRect: NSRect(x: bPX, y: bPY, width: 2, height: 4), xRadius: r, yRadius: r)
|
||||
if self.charging {
|
||||
NSColor.systemGreen.set()
|
||||
} else {
|
||||
NSColor.labelColor.set()
|
||||
}
|
||||
batteryPoint.lineWidth = 1.1
|
||||
batteryPoint.stroke()
|
||||
batteryPoint.fill()
|
||||
|
||||
let maxWidth = w-4.25
|
||||
let inner = NSBezierPath(roundedRect: NSRect(x: x+0.75, y: y+1.5, width: maxWidth*CGFloat(self.value), height: h-3), xRadius: 0.5, yRadius: 0.5)
|
||||
self.value.batteryColor().set()
|
||||
inner.lineWidth = 0
|
||||
inner.stroke()
|
||||
inner.close()
|
||||
inner.fill()
|
||||
|
||||
if self.charging {
|
||||
NSColor.systemGreen.set()
|
||||
} else {
|
||||
NSColor.labelColor.set()
|
||||
}
|
||||
battery.lineWidth = 0.8
|
||||
battery.stroke()
|
||||
}
|
||||
|
||||
func changeValue(value: Float) {
|
||||
if self.value != value {
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
func setCharging(value: Bool) {
|
||||
if self.charging != value {
|
||||
self.charging = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Battery: Module {
|
||||
let name: String = "Battery"
|
||||
var view: NSView = NSView()
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import IOKit.ps
|
||||
|
||||
class BatteryReader: Reader {
|
||||
var usage: Observable<Float>!
|
||||
@@ -38,7 +39,6 @@ class BatteryReader: Reader {
|
||||
}
|
||||
|
||||
func start() {
|
||||
_ = self.open()
|
||||
if updateTimer != nil {
|
||||
return
|
||||
}
|
||||
@@ -46,7 +46,6 @@ class BatteryReader: Reader {
|
||||
}
|
||||
|
||||
func stop() {
|
||||
_ = self.close()
|
||||
if updateTimer == nil {
|
||||
return
|
||||
}
|
||||
@@ -55,110 +54,21 @@ class BatteryReader: Reader {
|
||||
}
|
||||
|
||||
@objc func read() {
|
||||
var cap = charge()
|
||||
let charging = isCharging()
|
||||
let psInfo = IOPSCopyPowerSourcesInfo().takeRetainedValue()
|
||||
let psList = IOPSCopyPowerSourcesList(psInfo).takeRetainedValue() as [CFTypeRef]
|
||||
|
||||
if !charging {
|
||||
cap = 0 - cap
|
||||
for ps in psList {
|
||||
if let psDesc = IOPSGetPowerSourceDescription(psInfo, ps).takeUnretainedValue() as? [String: Any] {
|
||||
// let type = psDesc[kIOPSTypeKey] as? String
|
||||
let isCharging = (psDesc[kIOPSIsChargingKey] as? Bool)
|
||||
var cap: Float = Float(psDesc[kIOPSCurrentCapacityKey] as! Int) / 100
|
||||
|
||||
if !isCharging! {
|
||||
cap = 0 - cap
|
||||
}
|
||||
|
||||
self.usage << Float(cap)
|
||||
}
|
||||
}
|
||||
|
||||
self.usage << Float(cap)
|
||||
}
|
||||
|
||||
public func open() -> kern_return_t {
|
||||
if (service != 0) {
|
||||
#if DEBUG
|
||||
print("WARNING - \(#file):\(#function) - connection already open")
|
||||
#endif
|
||||
return kIOReturnStillOpen
|
||||
}
|
||||
|
||||
service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching("AppleSmartBattery"))
|
||||
|
||||
if (service == 0) {
|
||||
#if DEBUG
|
||||
print("ERROR - \(#file):\(#function) - service not found")
|
||||
#endif
|
||||
return kIOReturnNotFound
|
||||
}
|
||||
|
||||
return kIOReturnSuccess
|
||||
}
|
||||
|
||||
public func close() -> kern_return_t {
|
||||
let result = IOObjectRelease(service)
|
||||
service = 0
|
||||
|
||||
#if DEBUG
|
||||
if (result != kIOReturnSuccess) {
|
||||
print("ERROR - \(#file):\(#function) - Failed to close")
|
||||
}
|
||||
#endif
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
public func maxCapactiy() -> Int {
|
||||
let prop = IORegistryEntryCreateCFProperty(service, Key.MaxCapacity.rawValue as CFString, kCFAllocatorDefault, 0)
|
||||
|
||||
if prop != nil {
|
||||
return prop!.takeUnretainedValue() as! Int
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
public func currentCapacity() -> Int {
|
||||
let prop = IORegistryEntryCreateCFProperty(service, Key.CurrentCapacity.rawValue as CFString, kCFAllocatorDefault, 0)
|
||||
|
||||
if prop != nil {
|
||||
return prop!.takeUnretainedValue() as! Int
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
public func isACPowered() -> Bool {
|
||||
let prop = IORegistryEntryCreateCFProperty(service, Key.ACPowered.rawValue as CFString, kCFAllocatorDefault, 0)
|
||||
|
||||
if prop != nil {
|
||||
return prop!.takeUnretainedValue() as! Bool
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public func isCharging() -> Bool {
|
||||
let prop = IORegistryEntryCreateCFProperty(service, Key.IsCharging.rawValue as CFString, kCFAllocatorDefault, 0)
|
||||
|
||||
if prop != nil {
|
||||
return prop!.takeUnretainedValue() as! Bool
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public func isCharged() -> Bool {
|
||||
let prop = IORegistryEntryCreateCFProperty(service, Key.FullyCharged.rawValue as CFString, kCFAllocatorDefault, 0)
|
||||
|
||||
if prop != nil {
|
||||
return prop!.takeUnretainedValue() as! Bool
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public func charge() -> Double {
|
||||
let ccap = Double(currentCapacity())
|
||||
let mcap = Double(maxCapactiy())
|
||||
|
||||
if ccap != 0 && mcap != 0 {
|
||||
return ccap / mcap
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
public func timeRemaining() -> Int {
|
||||
let prop = IORegistryEntryCreateCFProperty(service, Key.TimeRemaining.rawValue as CFString, kCFAllocatorDefault, 0)
|
||||
|
||||
if prop != nil {
|
||||
return prop!.takeUnretainedValue() as! Int
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
88
Stats/Modules/Battery/BatteryView.swift
Normal file
88
Stats/Modules/Battery/BatteryView.swift
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// BatteryView.swift
|
||||
// Stats
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 14/06/2019.
|
||||
// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
class BatteryView: NSView {
|
||||
var value: Float {
|
||||
didSet {
|
||||
self.needsDisplay = true
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
}
|
||||
var charging: Bool {
|
||||
didSet {
|
||||
self.needsDisplay = true
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
}
|
||||
|
||||
override init(frame: NSRect) {
|
||||
self.value = 1.0
|
||||
self.charging = false
|
||||
super.init(frame: frame)
|
||||
self.wantsLayer = true
|
||||
self.addSubview(NSView())
|
||||
}
|
||||
|
||||
required init?(coder decoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
super.draw(dirtyRect)
|
||||
|
||||
let x: CGFloat = 4.0
|
||||
let 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
|
||||
|
||||
let battery = NSBezierPath(roundedRect: NSRect(x: x-1, y: y, width: w-1, height: h), xRadius: r, yRadius: r)
|
||||
|
||||
let bPX: CGFloat = x+w-2
|
||||
let bPY: CGFloat = (dirtyRect.size.height / 2) - 2
|
||||
let batteryPoint = NSBezierPath(roundedRect: NSRect(x: bPX, y: bPY, width: 2, height: 4), xRadius: r, yRadius: r)
|
||||
if self.charging {
|
||||
NSColor.systemGreen.set()
|
||||
} else {
|
||||
NSColor.labelColor.set()
|
||||
}
|
||||
batteryPoint.lineWidth = 1.1
|
||||
batteryPoint.stroke()
|
||||
batteryPoint.fill()
|
||||
|
||||
let maxWidth = w-4.25
|
||||
let inner = NSBezierPath(roundedRect: NSRect(x: x+0.75, y: y+1.5, width: maxWidth*CGFloat(self.value), height: h-3), xRadius: 0.5, yRadius: 0.5)
|
||||
self.value.batteryColor().set()
|
||||
inner.lineWidth = 0
|
||||
inner.stroke()
|
||||
inner.close()
|
||||
inner.fill()
|
||||
|
||||
if self.charging {
|
||||
NSColor.systemGreen.set()
|
||||
} else {
|
||||
NSColor.labelColor.set()
|
||||
}
|
||||
battery.lineWidth = 0.8
|
||||
battery.stroke()
|
||||
}
|
||||
|
||||
func changeValue(value: Float) {
|
||||
if self.value != value {
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
func setCharging(value: Bool) {
|
||||
if self.charging != value {
|
||||
self.charging = value
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user