mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
58
CHANGELOG.md
Normal file
58
CHANGELOG.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
### [v1.2.5]
|
||||
- added chart bar widget for CPU, Memory and Disk module
|
||||
- label in Charts are enabled by default
|
||||
- color and label option are visible only if available in selected widget
|
||||
- fixed few bugs
|
||||
|
||||
### [v1.2.4]
|
||||
- fixed bug when widgets don't display properly (or don't shows at all)
|
||||
- initialized bar chart widget
|
||||
- fixed few bugs
|
||||
|
||||
### [v1.2.3]
|
||||
- new icon
|
||||
- small code refactoring
|
||||
- changed font style name of the indicator in the Chart/Chart with value
|
||||
- added dock icon visibility to preferences
|
||||
- moved color and label preference from global to local (now each module can be configurated separately)
|
||||
- now check for updates on start can be disabled in preferences
|
||||
- fixed few bugs
|
||||
|
||||
### [v1.2.2]
|
||||
- fully automated build and sign app process
|
||||
- fixed update and about visibility window in dark mode
|
||||
- added name of the indicators in the Chart/Chart with value
|
||||
- added check for new version on start
|
||||
- removed charts and charts with value to Disk module
|
||||
- now module submenu is disabled if module is disabled
|
||||
- fixed bug when network module stop working after turn on/of
|
||||
- fixed few bugs
|
||||
|
||||
### [v1.2.1]
|
||||
- added charts and charts with value to Disk module
|
||||
- fixed bug when Chart with value does not shows
|
||||
|
||||
### [v1.2.0]
|
||||
- added network module
|
||||
- added Check for updates window
|
||||
- fixed few bugs
|
||||
|
||||
### [v1.1.0]
|
||||
- added battery module
|
||||
- added chart widget for CPU and Memory
|
||||
- added About Stats window
|
||||
|
||||
### [v1.0.0]
|
||||
- first release
|
||||
|
||||
[v1.2.5]: https://github.com/exelban/stats/releases/tag/v1.2.5
|
||||
[v1.2.4]: https://github.com/exelban/stats/releases/tag/v1.2.4
|
||||
[v1.2.3]: https://github.com/exelban/stats/releases/tag/v1.2.3
|
||||
[v1.2.2]: https://github.com/exelban/stats/releases/tag/v1.2.2
|
||||
[v1.2.1]: https://github.com/exelban/stats/releases/tag/v1.2.1
|
||||
[v1.2.0]: https://github.com/exelban/stats/releases/tag/v1.2.0
|
||||
[v1.1.0]: https://github.com/exelban/stats/releases/tag/v1.1.0
|
||||
[v1.0.0]: https://github.com/exelban/stats/releases/tag/v1.0.0
|
||||
62
README.md
62
README.md
@@ -20,9 +20,9 @@ You can download latest version [here](https://github.com/exelban/stats/releases
|
||||
|
||||
| Name | Available widgets | Description |
|
||||
| --- | --- | --- |
|
||||
| **CPU** | Percentage / Chart / Chart with value | Shows CPU usage |
|
||||
| **Memory** | Percentage / Chart / Chart with value | Shows RAM usage |
|
||||
| **Disk** | Percentage | Shows disk utilization |
|
||||
| **CPU** | Percentage / Chart / Chart with value / Chart Bar | Shows CPU usage |
|
||||
| **Memory** | Percentage / Chart / Chart with value / Chart Bar | Shows RAM usage |
|
||||
| **Disk** | Percentage / Chart Bar | Shows disk utilization |
|
||||
| **Battery** | Graphic / Percentage | Shows battery level and charging status |
|
||||
| **Newtork** | Dots / Upload/Download traffic | Shows network activity |
|
||||
|
||||
@@ -32,63 +32,9 @@ You can download latest version [here](https://github.com/exelban/stats/releases
|
||||
| 10.13.6 *(High Sierra)* | **true** |
|
||||
| 10.14.1 *(Mojave)* | **true** |
|
||||
|
||||
## Todo
|
||||
- [X] Battery percentage
|
||||
- [X] Create new logo ([IconArchive](http://www.iconarchive.com/show/simple-icons-by-kxmylo/utilities-system-monitor-icon.html))
|
||||
- [ ] Window with preferences
|
||||
- [ ] Save last modules values
|
||||
- [X] Colors toggle for each module
|
||||
- [ ] temperature module
|
||||
- [X] battery module
|
||||
- [X] move to module system (CPU, RAM, DISK)
|
||||
- [X] network module
|
||||
- [X] save settings
|
||||
- [ ] OTA updates
|
||||
- [X] charts
|
||||
- [X] autostart on boot
|
||||
|
||||
## What's new
|
||||
[CHANGELOG](https://github.com/exelban/stats/blob/master/CHANGELOG.md)
|
||||
|
||||
### v1.2.4
|
||||
- fixed bug when widgets don't display properly (or don't shows at all)
|
||||
- initialized bar chart widget
|
||||
- fixed few bugs
|
||||
|
||||
### v1.2.3
|
||||
- new icon
|
||||
- small code refactoring
|
||||
- changed font style name of the indicator in the Chart/Chart with value
|
||||
- added dock icon visibility to preferences
|
||||
- moved color and label preference from global to local (now each module can be configurated separately)
|
||||
- now check for updates on start can be disabled in preferences
|
||||
- fixed few bugs
|
||||
|
||||
### v1.2.2
|
||||
- fully automated build and sign app process
|
||||
- fixed update and about visibility window in dark mode
|
||||
- added name of the indicators in the Chart/Chart with value
|
||||
- added check for new version on start
|
||||
- removed charts and charts with value to Disk module
|
||||
- now module submenu is disabled if module is disabled
|
||||
- fixed bug when network module stop working after turn on/of
|
||||
- fixed few bugs
|
||||
|
||||
### v1.2.1
|
||||
- added charts and charts with value to Disk module
|
||||
- fixed bug when Chart with value does not shows
|
||||
|
||||
### v1.2.0
|
||||
- added network module
|
||||
- added Check for updates window
|
||||
- fixed few bugs
|
||||
|
||||
### v1.1.0
|
||||
- added battery module
|
||||
- added chart widget for CPU and Memory
|
||||
- added About Stats window
|
||||
|
||||
### v1.0.0
|
||||
- first release
|
||||
|
||||
## License
|
||||
[MIT License](https://github.com/exelban/stats/blob/master/LICENSE)
|
||||
|
||||
@@ -36,17 +36,17 @@ class Battery: Module {
|
||||
}
|
||||
|
||||
func start() {
|
||||
if !self.reader.value.value.isNaN {
|
||||
if !self.reader.value.value.isEmpty {
|
||||
let value = self.reader.value!.value
|
||||
(self.view as! BatteryView).setCharging(value: value > 0)
|
||||
(self.view as! Widget).value(value: abs(value))
|
||||
(self.view as! BatteryView).setCharging(value: value.first! > 0)
|
||||
(self.view as! Widget).setValue(data: [abs(value.first!)])
|
||||
}
|
||||
|
||||
self.reader.start()
|
||||
self.reader.value.subscribe(observer: self) { (value, _) in
|
||||
if !value.isNaN {
|
||||
(self.view as! BatteryView).setCharging(value: value > 0)
|
||||
(self.view as! Widget).value(value: abs(value))
|
||||
if !value.isEmpty {
|
||||
(self.view as! BatteryView).setCharging(value: value.first! > 0)
|
||||
(self.view as! Widget).setValue(data: [abs(value.first!)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ import Foundation
|
||||
import IOKit.ps
|
||||
|
||||
class BatteryReader: Reader {
|
||||
var value: Observable<Double>!
|
||||
var value: Observable<[Double]>!
|
||||
var available: Bool = false
|
||||
var updateTimer: Timer!
|
||||
|
||||
init() {
|
||||
self.value = Observable(0)
|
||||
self.value = Observable([])
|
||||
read()
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class BatteryReader: Reader {
|
||||
cap = 0 - cap
|
||||
}
|
||||
|
||||
self.value << Double(cap)
|
||||
self.value << [Double(cap)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class CPU: Module {
|
||||
self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true)
|
||||
self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini
|
||||
self.color = Observable(defaults.object(forKey: "\(name)_color") != nil ? defaults.bool(forKey: "\(name)_color") : false)
|
||||
self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : false)
|
||||
self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : true)
|
||||
initMenu()
|
||||
initWidget()
|
||||
}
|
||||
@@ -61,22 +61,26 @@ class CPU: Module {
|
||||
barChart.target = self
|
||||
|
||||
let color = NSMenuItem(title: "Color", action: #selector(toggleColor), keyEquivalent: "")
|
||||
color.state = defaults.bool(forKey: "\(name)_color") ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
color.state = self.color.value ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
color.target = self
|
||||
|
||||
let label = NSMenuItem(title: "Label", action: #selector(toggleLabel), keyEquivalent: "")
|
||||
label.state = defaults.bool(forKey: "\(name)_label") || defaults.object(forKey: "\(name)_label") == nil ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
label.state = self.label.value ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
label.target = self
|
||||
|
||||
submenu.addItem(mini)
|
||||
submenu.addItem(chart)
|
||||
submenu.addItem(chartWithValue)
|
||||
// submenu.addItem(barChart)
|
||||
submenu.addItem(barChart)
|
||||
|
||||
submenu.addItem(NSMenuItem.separator())
|
||||
|
||||
submenu.addItem(label)
|
||||
submenu.addItem(color)
|
||||
if self.widgetType == Widgets.BarChart || self.widgetType == Widgets.ChartWithValue || self.widgetType == Widgets.Chart {
|
||||
submenu.addItem(label)
|
||||
}
|
||||
if self.widgetType == Widgets.Mini || self.widgetType == Widgets.ChartWithValue {
|
||||
submenu.addItem(color)
|
||||
}
|
||||
|
||||
menu.submenu = submenu
|
||||
}
|
||||
@@ -126,7 +130,8 @@ class CPU: Module {
|
||||
self.defaults.set(widgetCode, forKey: "\(name)_widget")
|
||||
self.widgetType = widgetCode
|
||||
self.active << false
|
||||
initWidget()
|
||||
self.initWidget()
|
||||
self.initMenu()
|
||||
self.active << true
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
class CPUReader: Reader {
|
||||
var value: Observable<Double>!
|
||||
var value: Observable<[Double]>!
|
||||
var available: Bool = true
|
||||
var cpuInfo: processor_info_array_t!
|
||||
var prevCpuInfo: processor_info_array_t?
|
||||
@@ -19,9 +19,11 @@ class CPUReader: Reader {
|
||||
var updateTimer: Timer!
|
||||
let CPUUsageLock: NSLock = NSLock()
|
||||
|
||||
var perCoreMode: Bool = true
|
||||
|
||||
init() {
|
||||
let mibKeys: [Int32] = [ CTL_HW, HW_NCPU ]
|
||||
self.value = Observable(0)
|
||||
self.value = Observable([])
|
||||
mibKeys.withUnsafeBufferPointer() { mib in
|
||||
var sizeOfNumCPUs: size_t = MemoryLayout<uint>.size
|
||||
let status = sysctl(processor_info_array_t(mutating: mib.baseAddress), 2, &numCPUs, &sizeOfNumCPUs, nil, 0)
|
||||
@@ -55,6 +57,8 @@ class CPUReader: Reader {
|
||||
|
||||
var inUseOnAllCores: Int32 = 0
|
||||
var totalOnAllCores: Int32 = 0
|
||||
var usagePerCore: [Double] = []
|
||||
|
||||
for i in 0 ..< Int32(numCPUs) {
|
||||
var inUse: Int32
|
||||
var total: Int32
|
||||
@@ -76,8 +80,14 @@ class CPUReader: Reader {
|
||||
|
||||
inUseOnAllCores = inUseOnAllCores + inUse
|
||||
totalOnAllCores = totalOnAllCores + total
|
||||
usagePerCore.insert((Double(inUse) / Double(total)), at: Int(i))
|
||||
}
|
||||
|
||||
if perCoreMode {
|
||||
self.value << usagePerCore
|
||||
} else {
|
||||
self.value << [(Double(inUseOnAllCores) / Double(totalOnAllCores))]
|
||||
}
|
||||
self.value << (Double(inUseOnAllCores) / Double(totalOnAllCores))
|
||||
|
||||
CPUUsageLock.unlock()
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class Disk: Module {
|
||||
self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true)
|
||||
self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini
|
||||
self.color = Observable(defaults.object(forKey: "\(name)_color") != nil ? defaults.bool(forKey: "\(name)_color") : false)
|
||||
self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : false)
|
||||
self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : true)
|
||||
|
||||
self.initMenu()
|
||||
self.initWidget()
|
||||
@@ -48,11 +48,33 @@ class Disk: Module {
|
||||
}
|
||||
menu.target = self
|
||||
|
||||
let mini = NSMenuItem(title: "Mini", action: #selector(toggleWidget), keyEquivalent: "")
|
||||
mini.state = self.widgetType == Widgets.Mini ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
mini.target = self
|
||||
|
||||
let barChart = NSMenuItem(title: "Bar chart", action: #selector(toggleWidget), keyEquivalent: "")
|
||||
barChart.state = self.widgetType == Widgets.BarChart ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
barChart.target = self
|
||||
|
||||
let color = NSMenuItem(title: "Color", action: #selector(toggleColor), keyEquivalent: "")
|
||||
color.state = defaults.bool(forKey: "\(name)_color") ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
color.state = self.color.value ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
color.target = self
|
||||
|
||||
submenu.addItem(color)
|
||||
let label = NSMenuItem(title: "Label", action: #selector(toggleLabel), keyEquivalent: "")
|
||||
label.state = self.label.value ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
label.target = self
|
||||
|
||||
submenu.addItem(mini)
|
||||
submenu.addItem(barChart)
|
||||
|
||||
submenu.addItem(NSMenuItem.separator())
|
||||
|
||||
if self.widgetType == Widgets.BarChart {
|
||||
submenu.addItem(label)
|
||||
}
|
||||
if self.widgetType == Widgets.Mini {
|
||||
submenu.addItem(color)
|
||||
}
|
||||
|
||||
menu.submenu = submenu
|
||||
}
|
||||
@@ -71,9 +93,48 @@ class Disk: Module {
|
||||
}
|
||||
}
|
||||
|
||||
@objc func toggleWidget(_ sender: NSMenuItem) {
|
||||
var widgetCode: Float = 0.0
|
||||
|
||||
switch sender.title {
|
||||
case "Mini":
|
||||
widgetCode = Widgets.Mini
|
||||
case "Bar chart":
|
||||
widgetCode = Widgets.BarChart
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if self.widgetType == widgetCode {
|
||||
return
|
||||
}
|
||||
|
||||
for item in self.submenu.items {
|
||||
if item.title == "Mini" || item.title == "Bar chart" {
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
}
|
||||
|
||||
sender.state = sender.state == NSControl.StateValue.on ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(widgetCode, forKey: "\(name)_widget")
|
||||
self.widgetType = widgetCode
|
||||
self.active << false
|
||||
self.initMenu()
|
||||
self.initWidget()
|
||||
self.active << true
|
||||
}
|
||||
|
||||
@objc func toggleColor(_ sender: NSMenuItem) {
|
||||
sender.state = sender.state == NSControl.StateValue.on ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(sender.state == NSControl.StateValue.on, forKey: "\(name)_color")
|
||||
self.color << (sender.state == NSControl.StateValue.on)
|
||||
}
|
||||
|
||||
@objc func toggleLabel(_ sender: NSMenuItem) {
|
||||
sender.state = sender.state == NSControl.StateValue.on ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(sender.state == NSControl.StateValue.on, forKey: "\(name)_label")
|
||||
self.active << false
|
||||
self.label << (sender.state == NSControl.StateValue.on)
|
||||
self.active << true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
import Foundation
|
||||
|
||||
class DiskReader: Reader {
|
||||
var value: Observable<Double>!
|
||||
var value: Observable<[Double]>!
|
||||
var available: Bool = true
|
||||
var updateTimer: Timer!
|
||||
|
||||
init() {
|
||||
self.value = Observable(0)
|
||||
self.value = Observable([])
|
||||
read()
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class DiskReader: Reader {
|
||||
let free = freeDiskSpaceInBytes()
|
||||
let usedSpace = total - free
|
||||
|
||||
self.value << (Double(usedSpace) / Double(total))
|
||||
self.value << [(Double(usedSpace) / Double(total))]
|
||||
}
|
||||
|
||||
func totalDiskSpaceInBytes() -> Int64 {
|
||||
|
||||
@@ -30,7 +30,7 @@ class Memory: Module {
|
||||
self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true)
|
||||
self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini
|
||||
self.color = Observable(defaults.object(forKey: "\(name)_color") != nil ? defaults.bool(forKey: "\(name)_color") : false)
|
||||
self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : false)
|
||||
self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : true)
|
||||
initMenu()
|
||||
initWidget()
|
||||
}
|
||||
@@ -58,22 +58,31 @@ class Memory: Module {
|
||||
chartWithValue.state = self.widgetType == Widgets.ChartWithValue ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
chartWithValue.target = self
|
||||
|
||||
let barChart = NSMenuItem(title: "Bar chart", action: #selector(toggleWidget), keyEquivalent: "")
|
||||
barChart.state = self.widgetType == Widgets.BarChart ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
barChart.target = self
|
||||
|
||||
let color = NSMenuItem(title: "Color", action: #selector(toggleColor), keyEquivalent: "")
|
||||
color.state = defaults.bool(forKey: "\(name)_color") ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
color.state = self.color.value ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
color.target = self
|
||||
|
||||
let label = NSMenuItem(title: "Label", action: #selector(toggleLabel), keyEquivalent: "")
|
||||
label.state = defaults.bool(forKey: "\(name)_label") || defaults.object(forKey: "\(name)_label") == nil ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
label.state = self.label.value ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
label.target = self
|
||||
|
||||
submenu.addItem(mini)
|
||||
submenu.addItem(chart)
|
||||
submenu.addItem(chartWithValue)
|
||||
submenu.addItem(barChart)
|
||||
|
||||
submenu.addItem(NSMenuItem.separator())
|
||||
|
||||
submenu.addItem(label)
|
||||
submenu.addItem(color)
|
||||
if self.widgetType == Widgets.BarChart || self.widgetType == Widgets.ChartWithValue || self.widgetType == Widgets.Chart {
|
||||
submenu.addItem(label)
|
||||
}
|
||||
if self.widgetType == Widgets.Mini || self.widgetType == Widgets.ChartWithValue {
|
||||
submenu.addItem(color)
|
||||
}
|
||||
|
||||
menu.submenu = submenu
|
||||
}
|
||||
@@ -115,7 +124,7 @@ class Memory: Module {
|
||||
}
|
||||
|
||||
for item in self.submenu.items {
|
||||
if item.title == "Mini" || item.title == "Chart" || item.title == "Chart with value" {
|
||||
if item.title == "Mini" || item.title == "Chart" || item.title == "Chart with value" || item.title == "Bar chart" {
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
}
|
||||
@@ -125,6 +134,7 @@ class Memory: Module {
|
||||
self.widgetType = widgetCode
|
||||
self.active << false
|
||||
self.initWidget()
|
||||
self.initMenu()
|
||||
self.active << true
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
import Foundation
|
||||
|
||||
class MemoryReader: Reader {
|
||||
var value: Observable<Double>!
|
||||
var value: Observable<[Double]>!
|
||||
var available: Bool = true
|
||||
var updateTimer: Timer!
|
||||
var totalSize: Float
|
||||
|
||||
init() {
|
||||
self.value = Observable(0)
|
||||
self.value = Observable([])
|
||||
var stats = host_basic_info()
|
||||
var count = UInt32(MemoryLayout<host_basic_info_data_t>.size / MemoryLayout<integer_t>.size)
|
||||
|
||||
@@ -68,7 +68,7 @@ class MemoryReader: Reader {
|
||||
let compressed = Float(stats.compressor_page_count) * Float(PAGE_SIZE)
|
||||
|
||||
let free = totalSize - (active + wired + compressed)
|
||||
self.value << Double((totalSize - free) / totalSize)
|
||||
self.value << [Double((totalSize - free) / totalSize)]
|
||||
}
|
||||
else {
|
||||
print("Error with host_statistics64(): " + (String(cString: mach_error_string(kerr), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
|
||||
@@ -55,26 +55,26 @@ extension Module {
|
||||
}
|
||||
|
||||
widget.label = self.shortName
|
||||
widget.color(state: self.color.value)
|
||||
widget.label(state: self.label.value)
|
||||
widget.toggleColor(state: self.color.value)
|
||||
widget.toggleLabel(state: self.label.value)
|
||||
self.view = widget as! NSView
|
||||
}
|
||||
|
||||
func start() {
|
||||
if !self.reader.value.value.isNaN {
|
||||
if !self.reader.value.value.isEmpty {
|
||||
guard let widget = self.view as? Widget else {
|
||||
return
|
||||
}
|
||||
widget.value(value: self.reader.value.value)
|
||||
widget.setValue(data: self.reader.value.value)
|
||||
}
|
||||
|
||||
self.reader.start()
|
||||
self.reader.value.subscribe(observer: self) { (value, _) in
|
||||
if !value.isNaN {
|
||||
if !value.isEmpty {
|
||||
guard let widget = self.view as? Widget else {
|
||||
return
|
||||
}
|
||||
widget.value(value: value)
|
||||
widget.setValue(data: value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ extension Module {
|
||||
guard let widget = self.view as? Widget else {
|
||||
return
|
||||
}
|
||||
widget.color(state: value)
|
||||
widget.toggleColor(state: value)
|
||||
widget.redraw()
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ extension Module {
|
||||
guard let widget = self.view as? Widget else {
|
||||
return
|
||||
}
|
||||
widget.label(state: value)
|
||||
widget.toggleLabel(state: value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ class Network: Module {
|
||||
self.reader.start()
|
||||
|
||||
self.reader.value.subscribe(observer: self) { (value, _) in
|
||||
if !value.isNaN {
|
||||
(self.view as! Widget).value(value: value)
|
||||
if !value.isEmpty {
|
||||
(self.view as! Widget).setValue(data: value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import Cocoa
|
||||
|
||||
class NetworkReader: Reader {
|
||||
var value: Observable<Double>!
|
||||
var value: Observable<[Double]>!
|
||||
var available: Bool = true
|
||||
var updateTimer: Timer!
|
||||
|
||||
@@ -17,7 +17,7 @@ class NetworkReader: Reader {
|
||||
var pipe: Pipe = Pipe()
|
||||
|
||||
init() {
|
||||
self.value = Observable(0)
|
||||
self.value = Observable([])
|
||||
netProcess.launchPath = "/usr/bin/env"
|
||||
netProcess.arguments = ["netstat", "-w1", "-l", "en0"]
|
||||
netProcess.standardOutput = pipe
|
||||
@@ -51,7 +51,7 @@ class NetworkReader: Reader {
|
||||
return
|
||||
}
|
||||
|
||||
self.value << value
|
||||
self.value << [value]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
protocol Reader {
|
||||
var value: Observable<Double>! { get }
|
||||
var value: Observable<[Double]>! { get }
|
||||
|
||||
var available: Bool { get }
|
||||
var updateTimer: Timer! { get set }
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.2.4</string>
|
||||
<string>1.2.5</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
|
||||
@@ -41,9 +41,8 @@ class BarChart: NSView, Widget {
|
||||
super.draw(dirtyRect)
|
||||
|
||||
let gradientColor: NSColor = NSColor(red: (26/255.0), green: (126/255.0), blue: (252/255.0), alpha: 0.8)
|
||||
|
||||
let width = self.frame.size.width - (MODULE_MARGIN * 2)
|
||||
let height = self.frame.size.height - (MODULE_MARGIN * 2) + 1
|
||||
let height = self.frame.size.height - (MODULE_MARGIN * 2)
|
||||
|
||||
var x = MODULE_MARGIN
|
||||
if labelEnabled {
|
||||
@@ -59,7 +58,10 @@ class BarChart: NSView, Widget {
|
||||
|
||||
for i in 0..<partitions.count {
|
||||
let partitionValue = partitions[i]
|
||||
let partitonHeight = (((height - 4.8) * CGFloat(partitionValue)) / 1)
|
||||
var partitonHeight = ((height * CGFloat(partitionValue)) / 1)
|
||||
if partitonHeight < 1 {
|
||||
partitonHeight = 1
|
||||
}
|
||||
let partition = NSBezierPath(rect: NSRect(x: x, y: MODULE_MARGIN, width: partitionWidth - 0.5, height: partitonHeight))
|
||||
gradientColor.setFill()
|
||||
partition.fill()
|
||||
@@ -93,13 +95,11 @@ class BarChart: NSView, Widget {
|
||||
}
|
||||
}
|
||||
|
||||
func value(value: Double) {
|
||||
if self.partitions[0] != value {
|
||||
self.partitions[0] = value
|
||||
}
|
||||
func setValue(data: [Double]) {
|
||||
self.partitions = data
|
||||
}
|
||||
|
||||
func label(state: Bool) {
|
||||
func toggleLabel(state: Bool) {
|
||||
labelEnabled = state
|
||||
var width = self.frame.size.width
|
||||
if width == MODULE_WIDTH + 10 && state {
|
||||
@@ -110,13 +110,22 @@ class BarChart: NSView, Widget {
|
||||
self.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: width, height: self.frame.size.height)
|
||||
}
|
||||
|
||||
func color(state: Bool) {
|
||||
func toggleColor(state: Bool) {
|
||||
if self.color != state {
|
||||
self.color = state
|
||||
}
|
||||
}
|
||||
|
||||
func redraw() {
|
||||
var width: CGFloat = 18
|
||||
if self.labelEnabled {
|
||||
width += labelPadding
|
||||
}
|
||||
|
||||
if self.partitions.count == 1 && self.frame.size.width != width{
|
||||
self.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: width, height: self.frame.size.height)
|
||||
}
|
||||
|
||||
self.needsDisplay = true
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
|
||||
@@ -121,7 +121,8 @@ class BatteryView: NSView, Widget {
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
|
||||
func value(value: Double) {
|
||||
func setValue(data: [Double]) {
|
||||
let value: Double = data.first!
|
||||
if self.value != value {
|
||||
self.value = value
|
||||
|
||||
@@ -131,13 +132,13 @@ class BatteryView: NSView, Widget {
|
||||
}
|
||||
}
|
||||
|
||||
func color(state: Bool) {
|
||||
func toggleColor(state: Bool) {
|
||||
if self.color != state {
|
||||
self.color = state
|
||||
}
|
||||
}
|
||||
|
||||
func label(state: Bool) {}
|
||||
func toggleLabel(state: Bool) {}
|
||||
|
||||
func setCharging(value: Bool) {
|
||||
if self.charging != value {
|
||||
|
||||
@@ -124,7 +124,9 @@ class Chart: NSView, Widget {
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
|
||||
func value(value: Double) {
|
||||
func setValue(data: [Double]) {
|
||||
let value: Double = data.first!
|
||||
|
||||
if self.points.count < 50 {
|
||||
self.points.append(value)
|
||||
return
|
||||
@@ -139,13 +141,13 @@ class Chart: NSView, Widget {
|
||||
}
|
||||
}
|
||||
|
||||
func color(state: Bool) {
|
||||
func toggleColor(state: Bool) {
|
||||
if self.color != state {
|
||||
self.color = state
|
||||
}
|
||||
}
|
||||
|
||||
func label(state: Bool) {
|
||||
func toggleLabel(state: Bool) {
|
||||
labelEnabled = state
|
||||
var width = self.size
|
||||
if state {
|
||||
@@ -169,7 +171,9 @@ class ChartWithValue: Chart {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func value(value: Double) {
|
||||
override func setValue(data: [Double]) {
|
||||
let value: Double = data.first!
|
||||
|
||||
self.valueLabel.stringValue = "\(Int(Float(value.roundTo(decimalPlaces: 2))! * 100))%"
|
||||
self.valueLabel.textColor = value.usageColor(color: self.color)
|
||||
|
||||
@@ -187,7 +191,7 @@ class ChartWithValue: Chart {
|
||||
}
|
||||
}
|
||||
|
||||
override func label(state: Bool) {
|
||||
override func toggleLabel(state: Bool) {
|
||||
labelEnabled = state
|
||||
var width = self.size
|
||||
if state {
|
||||
@@ -197,7 +201,7 @@ class ChartWithValue: Chart {
|
||||
self.drawValue()
|
||||
}
|
||||
|
||||
override func color(state: Bool) {
|
||||
override func toggleColor(state: Bool) {
|
||||
if self.color != state {
|
||||
self.color = state
|
||||
self.valueLabel.textColor = self.points.last?.usageColor(color: state)
|
||||
|
||||
@@ -73,7 +73,8 @@ class Mini: NSView, Widget {
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
|
||||
func value(value: Double) {
|
||||
func setValue(data: [Double]) {
|
||||
let value: Double = data.first!
|
||||
if self.value != value {
|
||||
self.value = value
|
||||
|
||||
@@ -82,12 +83,12 @@ class Mini: NSView, Widget {
|
||||
}
|
||||
}
|
||||
|
||||
func color(state: Bool) {
|
||||
func toggleColor(state: Bool) {
|
||||
if self.color != state {
|
||||
self.color = state
|
||||
self.valueView.textColor = value.usageColor(color: state)
|
||||
}
|
||||
}
|
||||
|
||||
func label(state: Bool) {}
|
||||
func toggleLabel(state: Bool) {}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,9 @@ class NetworkDotsView: NSView, Widget {
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
|
||||
func value(value: Double) {
|
||||
func setValue(data: [Double]) {
|
||||
let value: Double = data.first!
|
||||
|
||||
let values = value.splitAtDecimal()
|
||||
if self.download != values[0] {
|
||||
self.download = values[0]
|
||||
@@ -76,14 +78,14 @@ class NetworkDotsView: NSView, Widget {
|
||||
}
|
||||
}
|
||||
|
||||
func color(state: Bool) {
|
||||
func toggleColor(state: Bool) {
|
||||
if self.color != state {
|
||||
self.color = state
|
||||
self.redraw()
|
||||
}
|
||||
}
|
||||
|
||||
func label(state: Bool) {}
|
||||
func toggleLabel(state: Bool) {}
|
||||
}
|
||||
|
||||
class NetworkTextView: NSView, Widget {
|
||||
@@ -113,20 +115,21 @@ class NetworkTextView: NSView, Widget {
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
|
||||
func value(value: Double) {
|
||||
func setValue(data: [Double]) {
|
||||
let value: Double = data.first!
|
||||
let values = value.splitAtDecimal()
|
||||
downloadValue.stringValue = Units(bytes: values[0]).getReadableUnit()
|
||||
uploadValue.stringValue = Units(bytes: values[1]).getReadableUnit()
|
||||
}
|
||||
|
||||
func color(state: Bool) {
|
||||
func toggleColor(state: Bool) {
|
||||
if self.color != state {
|
||||
self.color = state
|
||||
self.redraw()
|
||||
}
|
||||
}
|
||||
|
||||
func label(state: Bool) {}
|
||||
func toggleLabel(state: Bool) {}
|
||||
|
||||
func valueView() {
|
||||
downloadValue = NSTextField(frame: NSMakeRect(MODULE_MARGIN, MODULE_MARGIN, self.frame.size.width - MODULE_MARGIN, 9))
|
||||
@@ -230,7 +233,8 @@ class NetworkArrowsView: NSView, Widget {
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
|
||||
func value(value: Double) {
|
||||
func setValue(data: [Double]) {
|
||||
let value: Double = data.first!
|
||||
let values = value.splitAtDecimal()
|
||||
if self.download != values[0] {
|
||||
self.download = values[0]
|
||||
@@ -240,14 +244,14 @@ class NetworkArrowsView: NSView, Widget {
|
||||
}
|
||||
}
|
||||
|
||||
func color(state: Bool) {
|
||||
func toggleColor(state: Bool) {
|
||||
if self.color != state {
|
||||
self.color = state
|
||||
self.redraw()
|
||||
}
|
||||
}
|
||||
|
||||
func label(state: Bool) {}
|
||||
func toggleLabel(state: Bool) {}
|
||||
}
|
||||
|
||||
class NetworkDotsTextView: NSView, Widget {
|
||||
@@ -311,7 +315,8 @@ class NetworkDotsTextView: NSView, Widget {
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
|
||||
func value(value: Double) {
|
||||
func setValue(data: [Double]) {
|
||||
let value: Double = data.first!
|
||||
let values = value.splitAtDecimal()
|
||||
if self.download != values[0] {
|
||||
self.download = values[0]
|
||||
@@ -323,14 +328,14 @@ class NetworkDotsTextView: NSView, Widget {
|
||||
}
|
||||
}
|
||||
|
||||
func color(state: Bool) {
|
||||
func toggleColor(state: Bool) {
|
||||
if self.color != state {
|
||||
self.color = state
|
||||
self.redraw()
|
||||
}
|
||||
}
|
||||
|
||||
func label(state: Bool) {}
|
||||
func toggleLabel(state: Bool) {}
|
||||
|
||||
func valueView() {
|
||||
downloadValue = NSTextField(frame: NSMakeRect(MODULE_MARGIN, MODULE_MARGIN, self.frame.size.width - MODULE_MARGIN, 9))
|
||||
@@ -437,7 +442,8 @@ class NetworkArrowsTextView: NSView, Widget {
|
||||
setNeedsDisplay(self.frame)
|
||||
}
|
||||
|
||||
func value(value: Double) {
|
||||
func setValue(data: [Double]) {
|
||||
let value: Double = data.first!
|
||||
let values = value.splitAtDecimal()
|
||||
if self.download != values[0] {
|
||||
self.download = values[0]
|
||||
@@ -449,14 +455,14 @@ class NetworkArrowsTextView: NSView, Widget {
|
||||
}
|
||||
}
|
||||
|
||||
func color(state: Bool) {
|
||||
func toggleColor(state: Bool) {
|
||||
if self.color != state {
|
||||
self.color = state
|
||||
self.redraw()
|
||||
}
|
||||
}
|
||||
|
||||
func label(state: Bool) {}
|
||||
func toggleLabel(state: Bool) {}
|
||||
|
||||
func valueView() {
|
||||
downloadValue = NSTextField(frame: NSMakeRect(MODULE_MARGIN, MODULE_MARGIN, self.frame.size.width - MODULE_MARGIN, 9))
|
||||
|
||||
@@ -12,9 +12,9 @@ protocol Widget {
|
||||
var size: CGFloat { get }
|
||||
var label: String { get set }
|
||||
|
||||
func value(value: Double)
|
||||
func color(state: Bool)
|
||||
func label(state: Bool)
|
||||
func setValue(data: [Double])
|
||||
func toggleColor(state: Bool)
|
||||
func toggleLabel(state: Bool)
|
||||
|
||||
func redraw()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user