- added RAM pressure to BarChart widget

- added RAM pressure to LineChart widget
This commit is contained in:
Serhiy Mytrovtsiy
2020-06-30 23:11:40 +02:00
parent 5b6b393c3f
commit aab85cfdfd
9 changed files with 165 additions and 24 deletions

View File

@@ -16,9 +16,14 @@ public class BarChart: Widget {
private var labelState: Bool = true
private var boxState: Bool = true
private var colorState: Bool = false
private var pressureState: Bool = true
private let store: UnsafePointer<Store>?
private var value: [Double] = []
private var pressureLevel: Int = 0
private var pressureLevelSettingsView: NSView? = nil
private var colorizeSettingsView: NSView? = nil
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
var widgetTitle: String = title
@@ -58,6 +63,7 @@ public class BarChart: Widget {
self.boxState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_box", defaultValue: self.boxState)
self.labelState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_label", defaultValue: self.labelState)
self.colorState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_color", defaultValue: self.colorState)
self.pressureState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_pressure", defaultValue: self.pressureState)
}
if preview {
@@ -66,6 +72,7 @@ public class BarChart: Widget {
}
self.setFrameSize(NSSize(width: 36, height: self.frame.size.height))
self.invalidateIntrinsicContentSize()
self.pressureState = false
}
}
@@ -155,6 +162,8 @@ public class BarChart: Widget {
if self.colorState {
partitionValue.usageColor().setFill()
} else if self.pressureState {
self.pressureLevel.pressureColor().setFill()
} else {
NSColor.controlAccentColor.set()
}
@@ -175,13 +184,35 @@ public class BarChart: Widget {
})
}
public func setPressure(_ level: Int) {
guard self.pressureLevel != level else {
return
}
self.pressureLevel = level
DispatchQueue.main.async(execute: {
self.display()
})
}
public override func settings(superview: NSView) {
let rowHeight: CGFloat = 30
let height: CGFloat = ((rowHeight + Constants.Settings.margin) * 3) + Constants.Settings.margin
let settingsNumber: CGFloat = self.title == "RAM" ? 4 : 3
let height: CGFloat = ((rowHeight + Constants.Settings.margin) * settingsNumber) + Constants.Settings.margin
superview.setFrameSize(NSSize(width: superview.frame.width, height: height))
let view: NSView = NSView(frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin, width: superview.frame.width - (Constants.Settings.margin*2), height: superview.frame.height - (Constants.Settings.margin*2)))
if self.title == "RAM" {
self.pressureLevelSettingsView = ToggleTitleRow(
frame: NSRect(x: 0, y: (rowHeight + Constants.Settings.margin) * 3, width: view.frame.width, height: rowHeight),
title: "Pressure level",
action: #selector(togglePressure),
state: self.pressureState
)
view.addSubview(self.pressureLevelSettingsView!)
}
view.addSubview(ToggleTitleRow(
frame: NSRect(x: 0, y: (rowHeight + Constants.Settings.margin) * 2, width: view.frame.width, height: rowHeight),
title: "Label",
@@ -196,12 +227,13 @@ public class BarChart: Widget {
state: self.boxState
))
view.addSubview(ToggleTitleRow(
self.colorizeSettingsView = ToggleTitleRow(
frame: NSRect(x: 0, y: (rowHeight + Constants.Settings.margin) * 0, width: view.frame.width, height: rowHeight),
title: "Colorize",
action: #selector(toggleColor),
state: self.colorState
))
)
view.addSubview(self.colorizeSettingsView!)
superview.addSubview(view)
}
@@ -239,6 +271,32 @@ public class BarChart: Widget {
}
self.colorState = state! == .on ? true : false
self.store?.pointee.set(key: "\(self.title)_\(self.type.rawValue)_color", value: self.colorState)
if self.colorState {
self.pressureState = false
self.store?.pointee.set(key: "\(self.title)_\(self.type.rawValue)_pressure", value: self.pressureState)
ToggleNSControlState(self.pressureLevelSettingsView, state: .off)
}
self.display()
}
@objc private func togglePressure(_ sender: NSControl) {
var state: NSControl.StateValue? = nil
if #available(OSX 10.15, *) {
state = sender is NSSwitch ? (sender as! NSSwitch).state: nil
} else {
state = sender is NSButton ? (sender as! NSButton).state: nil
}
self.pressureState = state! == .on ? true : false
self.store?.pointee.set(key: "\(self.title)_\(self.type.rawValue)_pressure", value: self.pressureState)
if self.pressureState {
self.colorState = false
self.store?.pointee.set(key: "\(self.title)_\(self.type.rawValue)_color", value: self.colorState)
ToggleNSControlState(self.colorizeSettingsView, state: .off)
}
self.display()
}
}

View File

@@ -17,10 +17,12 @@ public class LineChart: Widget {
private var boxState: Bool = true
private var valueState: Bool = false
private var colorState: Bool = false
private var pressureState: Bool = true
private let store: UnsafePointer<Store>?
private var chart: LineChartView
private var value: Double = 0
private var pressureLevel: Int = 0
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
var widgetTitle: String = title
@@ -54,6 +56,7 @@ public class LineChart: Widget {
self.valueState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_value", defaultValue: self.valueState)
self.labelState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_label", defaultValue: self.labelState)
self.colorState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_color", defaultValue: self.colorState)
self.pressureState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_pressure", defaultValue: self.pressureState)
}
if self.labelState {
@@ -67,6 +70,7 @@ public class LineChart: Widget {
}
self.chart.points = list
self.value = 0.38
self.pressureState = false
}
}
@@ -142,6 +146,11 @@ public class LineChart: Widget {
}
chart.setFrameSize(NSSize(width: box.bounds.width - chartPadding, height: box.bounds.height - (chartPadding*2)))
if self.pressureState {
self.chart.color = self.pressureLevel.pressureColor()
} else {
self.chart.color = NSColor.controlAccentColor
}
chart.draw(NSRect(x: box.bounds.origin.x + 1, y: chartPadding, width: chart.frame.width, height: chart.frame.height))
ctx.restoreGState()
@@ -154,11 +163,21 @@ public class LineChart: Widget {
public override func settings(superview: NSView) {
let rowHeight: CGFloat = 30
let height: CGFloat = ((rowHeight + Constants.Settings.margin) * 4) + Constants.Settings.margin
let settingsNumber: CGFloat = self.title == "RAM" ? 5 : 4
let height: CGFloat = ((rowHeight + Constants.Settings.margin) * settingsNumber) + Constants.Settings.margin
superview.setFrameSize(NSSize(width: superview.frame.width, height: height))
let view: NSView = NSView(frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin, width: superview.frame.width - (Constants.Settings.margin*2), height: superview.frame.height - (Constants.Settings.margin*2)))
if self.title == "RAM" {
view.addSubview(ToggleTitleRow(
frame: NSRect(x: 0, y: (rowHeight + Constants.Settings.margin) * 4, width: view.frame.width, height: rowHeight),
title: "Pressure level",
action: #selector(togglePressure),
state: self.pressureState
))
}
view.addSubview(ToggleTitleRow(
frame: NSRect(x: 0, y: (rowHeight + Constants.Settings.margin) * 3, width: view.frame.width, height: rowHeight),
title: "Label",
@@ -205,6 +224,17 @@ public class LineChart: Widget {
})
}
public func setPressure(_ level: Int) {
guard self.pressureLevel != level else {
return
}
self.pressureLevel = level
DispatchQueue.main.async(execute: {
self.display()
})
}
@objc private func toggleLabel(_ sender: NSControl) {
var state: NSControl.StateValue? = nil
if #available(OSX 10.15, *) {
@@ -252,4 +282,16 @@ public class LineChart: Widget {
self.store?.pointee.set(key: "\(self.title)_\(self.type.rawValue)_color", value: self.colorState)
self.display()
}
@objc private func togglePressure(_ sender: NSControl) {
var state: NSControl.StateValue? = nil
if #available(OSX 10.15, *) {
state = sender is NSSwitch ? (sender as! NSSwitch).state: nil
} else {
state = sender is NSButton ? (sender as! NSButton).state: nil
}
self.pressureState = state! == .on ? true : false
self.store?.pointee.set(key: "\(self.title)_\(self.type.rawValue)_pressure", value: self.pressureState)
self.display()
}
}

View File

@@ -215,7 +215,7 @@ open class Module: Module_p {
// load and setup widget
private func setWidget() {
self.widget = LoadWidget(self.activeWidget, preview: false, title: self.config.name, config: self.config.widgetsConfig, store: self.store)
self.widget = LoadWidget(self.activeWidget, preview: false, name: self.config.name, config: self.config.widgetsConfig, store: self.store)
if self.widget == nil {
self.enabled = false
os_log(.error, log: log, "widget with type %s not found", "\(self.activeWidget)")

View File

@@ -120,7 +120,7 @@ open class Settings: NSView, Settings_p {
var x: CGFloat = Constants.Settings.margin
for i in 0...self.config.pointee.availableWidgets.count - 1 {
let widgetType = self.config.pointee.availableWidgets[i]
if let widget = LoadWidget(widgetType, preview: true, title: self.config.pointee.name, config: self.config.pointee.widgetsConfig, store: nil) {
if let widget = LoadWidget(widgetType, preview: true, name: self.config.pointee.name, config: self.config.pointee.widgetsConfig, store: nil) {
let preview = WidgetPreview(
frame: NSRect(x: x, y: Constants.Settings.margin, width: widget.frame.width, height: self.widgetSelectorHeight - (Constants.Settings.margin*2)),
title: self.config.pointee.name,

View File

@@ -72,31 +72,31 @@ open class Widget: NSView, Widget_p {
open func setValues(_ values: [value_t]) {}
}
func LoadWidget(_ type: widget_t, preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) -> Widget_p? {
func LoadWidget(_ type: widget_t, preview: Bool, name: String, config: NSDictionary?, store: UnsafePointer<Store>?) -> Widget_p? {
var widget: Widget_p? = nil
let widgetConfig: NSDictionary? = config?[type.rawValue] as? NSDictionary
switch type {
case .mini:
widget = Mini(preview: preview, title: title, config: widgetConfig, store: store)
widget = Mini(preview: preview, title: name, config: widgetConfig, store: store)
break
case .lineChart:
widget = LineChart(preview: preview, title: title, config: widgetConfig, store: store)
widget = LineChart(preview: preview, title: name, config: widgetConfig, store: store)
break
case .barChart:
widget = BarChart(preview: preview, title: title, config: widgetConfig, store: store)
widget = BarChart(preview: preview, title: name, config: widgetConfig, store: store)
break
case .network:
widget = NetworkWidget(preview: preview, title: title, config: widgetConfig, store: store)
widget = NetworkWidget(preview: preview, title: name, config: widgetConfig, store: store)
break
case .battery:
widget = BatterykWidget(preview: preview, title: title, config: widgetConfig, store: store)
widget = BatterykWidget(preview: preview, title: name, config: widgetConfig, store: store)
break
case .sensors:
widget = SensorsWidget(preview: preview, title: title, config: widgetConfig, store: store)
widget = SensorsWidget(preview: preview, title: name, config: widgetConfig, store: store)
break
case .disk:
widget = DiskWidget(preview: preview, title: title, config: widgetConfig, store: store)
widget = DiskWidget(preview: preview, title: name, config: widgetConfig, store: store)
break
default: break
}

View File

@@ -24,6 +24,8 @@ public struct RAM_Usage: value_t {
var used: Double?
var free: Double?
var pressureLevel: Int
public var widget_value: Double {
get {
return self.usage ?? 0
@@ -63,9 +65,11 @@ public class Memory: Module {
}
if let widget = self.widget as? LineChart {
widget.setValue(value!.usage ?? 0)
widget.setPressure(value?.pressureLevel ?? 0)
}
if let widget = self.widget as? BarChart {
widget.setValue([value!.usage ?? 0])
widget.setPressure(value?.pressureLevel ?? 0)
}
}
}

View File

@@ -29,7 +29,7 @@ internal class UsageReader: Reader<RAM_Usage> {
self.totalSize = Double(stats.max_mem)
return
}
self.totalSize = 0
print("Error with host_info(): " + (String(cString: mach_error_string(kerr), encoding: String.Encoding.ascii) ?? "unknown error"))
}
@@ -37,22 +37,26 @@ internal class UsageReader: Reader<RAM_Usage> {
public override func read() {
var stats = vm_statistics64()
var count = UInt32(MemoryLayout<vm_statistics64_data_t>.size / MemoryLayout<integer_t>.size)
let result: kern_return_t = withUnsafeMutablePointer(to: &stats) {
$0.withMemoryRebound(to: integer_t.self, capacity: 1) {
host_statistics64(mach_host_self(), HOST_VM_INFO64, $0, &count)
}
}
if result == KERN_SUCCESS {
let active = Double(stats.active_count) * Double(PAGE_SIZE)
let inactive = Double(stats.inactive_count) * Double(PAGE_SIZE)
let wired = Double(stats.wire_count) * Double(PAGE_SIZE)
let compressed = Double(stats.compressor_page_count) * Double(PAGE_SIZE)
let used = active + wired + compressed
let free = self.totalSize - used
var size: size_t = MemoryLayout<uint>.size
var pressureLevel: Int = 0
sysctlbyname("kern.memorystatus_vm_pressure_level", &pressureLevel, &size, nil, 0)
self.callback(RAM_Usage(
active: active,
inactive: inactive,
@@ -62,11 +66,13 @@ internal class UsageReader: Reader<RAM_Usage> {
usage: Double((self.totalSize - free) / self.totalSize),
total: Double(self.totalSize),
used: Double(used),
free: Double(free))
)
free: Double(free),
pressureLevel: pressureLevel
))
return
}
print("Error with host_statistics64(): " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
}
}

View File

@@ -24,6 +24,8 @@ public class LineChartView: NSView {
public var points: [Double]? = nil
public var transparent: Bool = true
public var color: NSColor = NSColor.controlAccentColor
public init(frame: NSRect, num: Int) {
self.points = Array(repeating: 0, count: num)
super.init(frame: frame)
@@ -40,10 +42,10 @@ public class LineChartView: NSView {
return
}
let lineColor: NSColor = NSColor.controlAccentColor
var gradientColor: NSColor = NSColor.controlAccentColor.withAlphaComponent(0.5)
let lineColor: NSColor = self.color
var gradientColor: NSColor = self.color.withAlphaComponent(0.5)
if !self.transparent {
gradientColor = NSColor.controlAccentColor.withAlphaComponent(0.8)
gradientColor = self.color.withAlphaComponent(0.8)
}
let context = NSGraphicsContext.current!.cgContext

View File

@@ -154,6 +154,21 @@ extension String: LocalizedError {
}
}
public extension Int {
func pressureColor() -> NSColor {
switch self {
case 1:
return NSColor.systemGreen
case 2:
return NSColor.systemYellow
case 3:
return NSColor.systemRed
default:
return NSColor.controlAccentColor
}
}
}
extension Float {
init?(_ bytes: [UInt8]) {
self = bytes.withUnsafeBytes {
@@ -559,3 +574,17 @@ public extension Array where Element : Equatable {
return true
}
}
public func ToggleNSControlState(_ view: NSView?, state: NSControl.StateValue) {
if let control = view?.subviews.first(where: { $0 is NSControl }) {
if #available(OSX 10.15, *) {
if let checkbox = control as? NSSwitch {
checkbox.state = state
}
} else {
if let checkbox = control as? NSButton {
checkbox.state = state
}
}
}
}