fix: trying to fix the crash by fixing some data racing in the widgets (#1578)

This commit is contained in:
Serhiy Mytrovtsiy
2023-08-19 09:39:18 +02:00
parent c5a3657957
commit 5030d22ec5
15 changed files with 198 additions and 349 deletions

View File

@@ -16,11 +16,11 @@ public class BarChart: WidgetWrapper {
private var boxState: Bool = true
private var frameState: Bool = false
private var colorState: Color = .systemAccent
private var colors: [Color] = Color.allCases
private var value: [[ColorValue]] = [[]]
private var pressureLevel: DispatchSource.MemoryPressureEvent = .normal
private var colorZones: colorZones = (0.6, 0.8)
private var _value: [[ColorValue]] = [[]]
private var _pressureLevel: DispatchSource.MemoryPressureEvent = .normal
private var _colorZones: colorZones = (0.6, 0.8)
private var boxSettingsView: NSView? = nil
private var frameSettingsView: NSView? = nil
@@ -38,7 +38,7 @@ public class BarChart: WidgetWrapper {
if let previewConfig = config!["Preview"] as? NSDictionary {
configuration = previewConfig
if let value = configuration["Value"] as? String {
self.value = value.split(separator: ",").map{ ([ColorValue(Double($0) ?? 0)]) }
self._value = value.split(separator: ",").map{ ([ColorValue(Double($0) ?? 0)]) }
}
}
}
@@ -53,7 +53,7 @@ public class BarChart: WidgetWrapper {
self.colors = self.colors.filter{ !unsupportedColors.contains($0.key) }
}
if let color = configuration["Color"] as? String {
if let defaultColor = colors.first(where: { "\($0.self)" == color }) {
if let defaultColor = self.colors.first(where: { "\($0.self)" == color }) {
self.colorState = defaultColor
}
}
@@ -76,8 +76,8 @@ public class BarChart: WidgetWrapper {
}
if preview {
if self.value.isEmpty {
self.value = [[ColorValue(0.72)], [ColorValue(0.38)]]
if self._value.isEmpty {
self._value = [[ColorValue(0.72)], [ColorValue(0.38)]]
}
self.setFrameSize(NSSize(width: 36, height: self.frame.size.height))
self.invalidateIntrinsicContentSize()
@@ -92,12 +92,21 @@ public class BarChart: WidgetWrapper {
public override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
var value: [[ColorValue]] = []
var pressureLevel: DispatchSource.MemoryPressureEvent = .normal
var colorZones: colorZones = (0.6, 0.8)
self.queue.sync {
value = self._value
pressureLevel = self._pressureLevel
colorZones = self._colorZones
}
var width: CGFloat = Constants.Widget.margin.x*2
var x: CGFloat = 0
let lineWidth = 1 / (NSScreen.main?.backingScaleFactor ?? 1)
let offset = lineWidth / 2
switch self.value.count {
switch value.count {
case 0, 1:
width += 10 + (offset*2)
case 2:
@@ -155,23 +164,23 @@ public class BarChart: WidgetWrapper {
let widthForBarChart = box.bounds.width
let partitionMargin: CGFloat = 0.5
let partitionsMargin: CGFloat = (CGFloat(self.value.count - 1)) * partitionMargin / CGFloat(self.value.count - 1)
let partitionWidth: CGFloat = (widthForBarChart / CGFloat(self.value.count)) - CGFloat(partitionsMargin.isNaN ? 0 : partitionsMargin)
let partitionsMargin: CGFloat = (CGFloat(value.count - 1)) * partitionMargin / CGFloat(value.count - 1)
let partitionWidth: CGFloat = (widthForBarChart / CGFloat(value.count)) - CGFloat(partitionsMargin.isNaN ? 0 : partitionsMargin)
let maxPartitionHeight: CGFloat = box.bounds.height
x += offset
for i in 0..<self.value.count {
for i in 0..<value.count {
var y = offset
for a in 0..<self.value[i].count {
let partitionValue = self.value[i][a]
for a in 0..<value[i].count {
let partitionValue = value[i][a]
let partitionHeight = maxPartitionHeight * CGFloat(partitionValue.value)
let partition = NSBezierPath(rect: NSRect(x: x, y: y, width: partitionWidth, height: partitionHeight))
if partitionValue.color == nil {
switch self.colorState {
case .systemAccent: NSColor.controlAccentColor.set()
case .utilization: partitionValue.value.usageColor(zones: self.colorZones, reversed: self.title == "Battery").set()
case .pressure: self.pressureLevel.pressureColor().set()
case .utilization: partitionValue.value.usageColor(zones: colorZones, reversed: self.title == "Battery").set()
case .pressure: pressureLevel.pressureColor().set()
case .cluster: (partitionValue.value.clusterColor(i) ?? .controlAccentColor).set()
case .monochrome:
if self.boxState {
@@ -203,34 +212,25 @@ public class BarChart: WidgetWrapper {
self.setWidth(width)
}
public func setValue(_ value: [[ColorValue]]) {
guard self.value != value else {
return
}
self.value = value
public func setValue(_ newValue: [[ColorValue]]) {
guard self._value != newValue else { return }
self._value = newValue
DispatchQueue.main.async(execute: {
self.display()
})
}
public func setPressure(_ level: DispatchSource.MemoryPressureEvent) {
guard self.pressureLevel != level else {
return
}
self.pressureLevel = level
public func setPressure(_ newPressureLevel: DispatchSource.MemoryPressureEvent) {
guard self._pressureLevel != newPressureLevel else { return }
self._pressureLevel = newPressureLevel
DispatchQueue.main.async(execute: {
self.display()
})
}
public func setColorZones(_ zones: colorZones) {
guard self.colorZones != zones else {
return
}
self.colorZones = zones
public func setColorZones(_ newColorZones: colorZones) {
guard self._colorZones != newColorZones else { return }
self._colorZones = newColorZones
DispatchQueue.main.async(execute: {
self.display()
})
@@ -243,27 +243,27 @@ public class BarChart: WidgetWrapper {
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Label"),
action: #selector(toggleLabel),
action: #selector(self.toggleLabel),
state: self.labelState
))
self.boxSettingsView = toggleSettingRow(
title: localizedString("Box"),
action: #selector(toggleBox),
action: #selector(self.toggleBox),
state: self.boxState
)
view.addArrangedSubview(self.boxSettingsView!)
self.frameSettingsView = toggleSettingRow(
title: localizedString("Frame"),
action: #selector(toggleFrame),
action: #selector(self.toggleFrame),
state: self.frameState
)
view.addArrangedSubview(self.frameSettingsView!)
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Color"),
action: #selector(toggleColor),
action: #selector(self.toggleColor),
items: self.colors,
selected: self.colorState.key
))
@@ -272,25 +272,13 @@ public class BarChart: WidgetWrapper {
}
@objc private func toggleLabel(_ 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.labelState = state! == .on ? true : false
self.labelState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_label", value: self.labelState)
self.display()
}
@objc private func toggleBox(_ 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.boxState = state! == .on ? true : false
self.boxState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_box", value: self.boxState)
if self.frameState {
@@ -303,13 +291,7 @@ public class BarChart: WidgetWrapper {
}
@objc private func toggleFrame(_ 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.frameState = state! == .on ? true : false
self.frameState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_frame", value: self.frameState)
if self.boxState {
@@ -322,9 +304,7 @@ public class BarChart: WidgetWrapper {
}
@objc private func toggleColor(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let key = sender.representedObject as? String else { return }
if let newColor = self.colors.first(where: { $0.key == key }) {
self.colorState = newColor
}

View File

@@ -18,12 +18,11 @@ public class BatteryWidget: WidgetWrapper {
private var colorState: Bool = false
private var hideAdditionalWhenFull: Bool = true
private var percentage: Double? = nil
private var time: Int = 0
private var charging: Bool = false
private var ACStatus: Bool = false
private var lowPowerMode: Bool = false
private var optimizedCharging: Bool = false
private var _percentage: Double? = nil
private var _time: Int = 0
private var _charging: Bool = false
private var _ACStatus: Bool = false
private var _optimizedCharging: Bool = false
public init(title: String, config: NSDictionary?, preview: Bool = false) {
let widgetTitle: String = title
@@ -46,7 +45,7 @@ public class BatteryWidget: WidgetWrapper {
}
if preview {
self.percentage = 0.72
self._percentage = 0.72
self.additional = "none"
self.iconState = true
self.colorState = false
@@ -62,15 +61,28 @@ public class BatteryWidget: WidgetWrapper {
guard let ctx = NSGraphicsContext.current?.cgContext else { return }
var percentage: Double? = nil
var time: Int = 0
var charging: Bool = false
var ACStatus: Bool = false
var optimizedCharging: Bool = false
self.queue.sync {
percentage = self._percentage
time = self._time
charging = self._charging
ACStatus = self._ACStatus
optimizedCharging = self._optimizedCharging
}
var width: CGFloat = Constants.Widget.margin.x*2
var x: CGFloat = 0
let isShortTimeFormat: Bool = self.timeFormat == "short"
if !self.hideAdditionalWhenFull || (self.hideAdditionalWhenFull && self.percentage != 1 && !self.optimizedCharging) {
if !self.hideAdditionalWhenFull || (self.hideAdditionalWhenFull && percentage != 1 && !optimizedCharging) {
switch self.additional {
case "percentage":
var value = "n/a"
if let percentage = self.percentage {
if let percentage {
value = "\(Int((percentage.rounded(toPlaces: 2)) * 100))%"
}
let rowWidth = self.drawOneRow(value: value, x: x).rounded(.up)
@@ -78,30 +90,30 @@ public class BatteryWidget: WidgetWrapper {
x += rowWidth + Constants.Widget.spacing
case "time":
let rowWidth = self.drawOneRow(
value: Double(self.time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
value: Double(time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
x: x
).rounded(.up)
width += rowWidth + Constants.Widget.spacing
x += rowWidth + Constants.Widget.spacing
case "percentageAndTime":
var value = "n/a"
if let percentage = self.percentage {
if let percentage {
value = "\(Int((percentage.rounded(toPlaces: 2)) * 100))%"
}
let rowWidth = self.drawTwoRows(
first: value,
second: Double(self.time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
second: Double(time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
x: x
).rounded(.up)
width += rowWidth + Constants.Widget.spacing
x += rowWidth + Constants.Widget.spacing
case "timeAndPercentage":
var value = "n/a"
if let percentage = self.percentage {
if let percentage {
value = "\(Int((percentage.rounded(toPlaces: 2)) * 100))%"
}
let rowWidth = self.drawTwoRows(
first: Double(self.time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
first: Double(time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
second: value,
x: x
).rounded(.up)
@@ -143,14 +155,14 @@ public class BatteryWidget: WidgetWrapper {
ctx.restoreGState()
width += 2 // add battery point width
if let percentage = self.percentage {
if let percentage {
let maxWidth = batterySize.width - offset*2 - borderWidth*2 - 1
let innerWidth: CGFloat = max(1, maxWidth * CGFloat(percentage))
let innerOffset: CGFloat = -offset + borderWidth + 1
var colorState = self.colorState
let color = percentage.batteryColor(color: colorState)
if self.additional == "innerPercentage" && !self.ACStatus {
if self.additional == "innerPercentage" && !ACStatus {
colorState = false
let innerUnderground = NSBezierPath(roundedRect: NSRect(
x: batteryFrame.bounds.origin.x + innerOffset,
@@ -172,7 +184,7 @@ public class BatteryWidget: WidgetWrapper {
color.set()
inner.fill()
if self.additional == "innerPercentage" && !self.ACStatus {
if self.additional == "innerPercentage" && !ACStatus {
let style = NSMutableParagraphStyle()
style.alignment = .center
let attributes = [
@@ -206,14 +218,14 @@ public class BatteryWidget: WidgetWrapper {
NSAttributedString.init(string: "?", attributes: attributes).draw(with: rect)
}
if self.ACStatus {
if ACStatus {
let batteryCenter: CGPoint = CGPoint(
x: batteryFrame.bounds.origin.x + (batteryFrame.bounds.width/2),
y: batteryFrame.bounds.origin.y + (batteryFrame.bounds.height/2)
)
var points: [CGPoint] = []
if self.charging {
if charging {
let iconSize: CGSize = CGSize(width: 9, height: batterySize.height + 6)
let min = CGPoint(
x: batteryCenter.x - (iconSize.width/2),
@@ -332,28 +344,28 @@ public class BatteryWidget: WidgetWrapper {
var updated: Bool = false
let timeFormat: String = Store.shared.string(key: "\(self.title)_timeFormat", defaultValue: self.timeFormat)
if self.percentage != percentage {
self.percentage = percentage
if self._percentage != percentage {
self._percentage = percentage
updated = true
}
if let status = ACStatus, self.ACStatus != status {
self.ACStatus = status
if let status = ACStatus, self._ACStatus != status {
self._ACStatus = status
updated = true
}
if let charging = isCharging, self.charging != charging {
self.charging = charging
if let charging = isCharging, self._charging != charging {
self._charging = charging
updated = true
}
if let time = time, self.time != time {
self.time = time
if let time = time, self._time != time {
self._time = time
updated = true
}
if self.timeFormat != timeFormat {
self.timeFormat = timeFormat
updated = true
}
if let state = optimizedCharging, self.optimizedCharging != state {
self.optimizedCharging = state
if let state = optimizedCharging, self._optimizedCharging != state {
self._optimizedCharging = state
updated = true
}

View File

@@ -58,10 +58,7 @@ public class Label: WidgetWrapper {
}
public func setLabel(_ new: String) {
if self.label == new {
return
}
guard self.label != new else { return }
self.label = new
DispatchQueue.main.async(execute: {
self.needsDisplay = true

View File

@@ -28,8 +28,8 @@ public class LineChart: WidgetWrapper {
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
), num: 60)
private var colors: [Color] = Color.allCases.filter({ $0 != Color.cluster })
private var value: Double = 0
private var pressureLevel: DispatchSource.MemoryPressureEvent = .normal
private var _value: Double = 0
private var _pressureLevel: DispatchSource.MemoryPressureEvent = .normal
private var historyNumbers: [KeyValue_p] = [
KeyValue_t(key: "30", value: "30"),
@@ -115,7 +115,7 @@ public class LineChart: WidgetWrapper {
list.append(Double.random(in: 0..<1))
}
self.chart.points = list
self.value = 0.38
self._value = 0.38
}
}
@@ -128,6 +128,13 @@ public class LineChart: WidgetWrapper {
guard let context = NSGraphicsContext.current?.cgContext else { return }
var value: Double = 0
var pressureLevel: DispatchSource.MemoryPressureEvent = .normal
self.queue.sync {
value = self._value
pressureLevel = self._pressureLevel
}
var width = self.width + (Constants.Widget.margin.x*2)
var x: CGFloat = 0
let lineWidth = 1 / (NSScreen.main?.backingScaleFactor ?? 1)
@@ -138,7 +145,7 @@ public class LineChart: WidgetWrapper {
switch self.colorState {
case .systemAccent: color = .controlAccentColor
case .utilization: color = value.usageColor()
case .pressure: color = self.pressureLevel.pressureColor()
case .pressure: color = pressureLevel.pressureColor()
case .monochrome:
if self.boxState {
color = (isDarkMode ? NSColor.black : NSColor.white)
@@ -234,23 +241,17 @@ public class LineChart: WidgetWrapper {
self.setWidth(width)
}
public func setValue(_ value: Double) {
if self.value != value {
self.value = value
}
public func setValue(_ newValue: Double) {
guard self._value != newValue else { return }
self._value = newValue
DispatchQueue.main.async(execute: {
self.chart.addValue(value)
self.display()
})
}
public func setPressure(_ level: DispatchSource.MemoryPressureEvent) {
guard self.pressureLevel != level else {
return
}
self.pressureLevel = level
public func setPressure(_ newPressureLevel: DispatchSource.MemoryPressureEvent) {
guard self._pressureLevel != newPressureLevel else { return }
self._pressureLevel = newPressureLevel
DispatchQueue.main.async(execute: {
self.display()
})
@@ -263,53 +264,53 @@ public class LineChart: WidgetWrapper {
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Label"),
action: #selector(toggleLabel),
action: #selector(self.toggleLabel),
state: self.labelState
))
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Value"),
action: #selector(toggleValue),
action: #selector(self.toggleValue),
state: self.valueState
))
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Colorize value"),
action: #selector(toggleValueColor),
action: #selector(self.toggleValueColor),
state: self.valueColorState
))
self.boxSettingsView = toggleSettingRow(
title: localizedString("Box"),
action: #selector(toggleBox),
action: #selector(self.toggleBox),
state: self.boxState
)
view.addArrangedSubview(self.boxSettingsView!)
self.frameSettingsView = toggleSettingRow(
title: localizedString("Frame"),
action: #selector(toggleFrame),
action: #selector(self.toggleFrame),
state: self.frameState
)
view.addArrangedSubview(self.frameSettingsView!)
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Color"),
action: #selector(toggleColor),
action: #selector(self.toggleColor),
items: self.colors,
selected: self.colorState.key
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Number of reads in the chart"),
action: #selector(toggleHistoryCount),
action: #selector(self.toggleHistoryCount),
items: self.historyNumbers,
selected: "\(self.historyCount)"
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Scaling"),
action: #selector(toggleScale),
action: #selector(self.toggleScale),
items: Scale.allCases,
selected: self.scaleState.key
))
@@ -318,25 +319,13 @@ public class LineChart: WidgetWrapper {
}
@objc private func toggleLabel(_ 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.labelState = state! == .on ? true : false
self.labelState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_label", value: self.labelState)
self.display()
}
@objc private func toggleBox(_ 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.boxState = state! == .on ? true : false
self.boxState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_box", value: self.boxState)
if self.frameState {
@@ -349,13 +338,7 @@ public class LineChart: WidgetWrapper {
}
@objc private func toggleFrame(_ 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.frameState = state! == .on ? true : false
self.frameState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_frame", value: self.frameState)
if self.boxState {
@@ -368,59 +351,37 @@ public class LineChart: WidgetWrapper {
}
@objc private func toggleValue(_ 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.valueState = state! == .on ? true : false
self.valueState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_value", value: self.valueState)
self.display()
}
@objc private func toggleColor(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let key = sender.representedObject as? String else { return }
if let newColor = Color.allCases.first(where: { $0.key == key }) {
self.colorState = newColor
}
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_color", value: key)
self.display()
}
@objc private func toggleValueColor(_ 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.valueColorState = state! == .on ? true : false
self.valueColorState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_valueColor", value: self.valueColorState)
self.display()
}
@objc private func toggleHistoryCount(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String, let value = Int(key) else {
return
}
guard let key = sender.representedObject as? String, let value = Int(key) else { return }
self.historyCount = value
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_historyCount", value: value)
self.chart.reinit(value)
self.display()
}
@objc private func toggleScale(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let value = Scale.allCases.first(where: { $0.key == key }) else { return }
guard let key = sender.representedObject as? String,
let value = Scale.allCases.first(where: { $0.key == key }) else { return }
self.scaleState = value
self.chart.setScale(value)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_scale", value: key)

View File

@@ -115,13 +115,13 @@ public class MemoryWidget: WidgetWrapper {
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Reverse values order"),
action: #selector(toggleOrder),
action: #selector(self.toggleOrder),
state: self.orderReversedState
))
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Show symbols"),
action: #selector(toggleSymbols),
action: #selector(self.toggleSymbols),
state: self.symbolsState
))
@@ -129,27 +129,13 @@ public class MemoryWidget: WidgetWrapper {
}
@objc private func toggleOrder(_ 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.orderReversedState = state! == .on ? true : false
self.orderReversedState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_orderReversed", value: self.orderReversedState)
self.display()
}
@objc private func toggleSymbols(_ 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.symbolsState = state! == .on ? true : false
self.symbolsState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_symbols", value: self.symbolsState)
self.display()
}

View File

@@ -21,26 +21,23 @@ public class Mini: WidgetWrapper {
private let onlyValueWidth: CGFloat = 40
private var colors: [Color] = Color.allCases
private var colorZones: colorZones = (0.6, 0.8)
private var value: Double = 0
private var pressureLevel: DispatchSource.MemoryPressureEvent = .normal
private var _value: Double = 0
private var _pressureLevel: DispatchSource.MemoryPressureEvent = .normal
private var _colorZones: colorZones = (0.6, 0.8)
private var defaultLabel: String
private var label: String
private var _label: String
private var width: CGFloat {
get {
return (self.labelState ? 31 : 36) + (2*Constants.Widget.margin.x)
}
(self.labelState ? 31 : 36) + (2*Constants.Widget.margin.x)
}
private var alignment: NSTextAlignment {
get {
if let alignmentPair = Alignments.first(where: { $0.key == self.alignmentState }) {
return alignmentPair.additional as? NSTextAlignment ?? .left
}
return .left
if let alignmentPair = Alignments.first(where: { $0.key == self.alignmentState }) {
return alignmentPair.additional as? NSTextAlignment ?? .left
}
return .left
}
public init(title: String, config: NSDictionary?, preview: Bool = false) {
@@ -52,7 +49,7 @@ public class Mini: WidgetWrapper {
if let previewConfig = config!["Preview"] as? NSDictionary {
configuration = previewConfig
if let value = configuration["Value"] as? String {
self.value = Double(value) ?? 0
self._value = Double(value) ?? 0
}
}
}
@@ -74,7 +71,7 @@ public class Mini: WidgetWrapper {
}
self.defaultLabel = widgetTitle
self.label = widgetTitle
self._label = widgetTitle
super.init(.mini, title: widgetTitle, frame: CGRect(
x: 0,
y: Constants.Widget.margin.y,
@@ -98,6 +95,17 @@ public class Mini: WidgetWrapper {
public override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
var value: Double = 0
var pressureLevel: DispatchSource.MemoryPressureEvent = .normal
var colorZones: colorZones = (0.6, 0.8)
var label: String = ""
self.queue.sync {
value = self._value
pressureLevel = self._pressureLevel
colorZones = self._colorZones
label = self._label
}
let valueSize: CGFloat = self.labelState ? 12 : 14
var origin: CGPoint = CGPoint(x: Constants.Widget.margin.x, y: (Constants.Widget.height-valueSize)/2)
let style = NSMutableParagraphStyle()
@@ -113,7 +121,7 @@ public class Mini: WidgetWrapper {
NSAttributedString.Key.paragraphStyle: style
]
let rect = CGRect(x: origin.x, y: 12, width: self.width - (Constants.Widget.margin.x*2), height: 7)
let str = NSAttributedString.init(string: self.label, attributes: stringAttributes)
let str = NSAttributedString.init(string: label, attributes: stringAttributes)
str.draw(with: rect)
origin.y = 1
@@ -122,8 +130,8 @@ public class Mini: WidgetWrapper {
var color: NSColor = .controlAccentColor
switch self.colorState {
case .systemAccent: color = .controlAccentColor
case .utilization: color = value.usageColor(zones: self.colorZones, reversed: self.title == "BAT")
case .pressure: color = self.pressureLevel.pressureColor()
case .utilization: color = value.usageColor(zones: colorZones, reversed: self.title == "BAT")
case .pressure: color = pressureLevel.pressureColor()
case .monochrome: color = (isDarkMode ? NSColor.white : NSColor.black)
default: color = self.colorState.additional as? NSColor ?? .controlAccentColor
}
@@ -134,29 +142,23 @@ public class Mini: WidgetWrapper {
NSAttributedString.Key.paragraphStyle: style
]
let rect = CGRect(x: origin.x, y: origin.y, width: self.width - (Constants.Widget.margin.x*2), height: valueSize+1)
let str = NSAttributedString.init(string: "\(Int(self.value.rounded(toPlaces: 2) * 100))%", attributes: stringAttributes)
let str = NSAttributedString.init(string: "\(Int(value.rounded(toPlaces: 2) * 100))%", attributes: stringAttributes)
str.draw(with: rect)
self.setWidth(width)
}
public func setValue(_ value: Double) {
if self.value == value {
return
}
self.value = value
public func setValue(_ newValue: Double) {
guard self._value != newValue else { return }
self._value = newValue
DispatchQueue.main.async(execute: {
self.display()
})
}
public func setPressure(_ level: DispatchSource.MemoryPressureEvent) {
if self.pressureLevel == level {
return
}
self.pressureLevel = level
public func setPressure(_ newPressureLevel: DispatchSource.MemoryPressureEvent) {
guard self._pressureLevel != newPressureLevel else { return }
self._pressureLevel = newPressureLevel
DispatchQueue.main.async(execute: {
self.needsDisplay = true
})
@@ -167,23 +169,16 @@ public class Mini: WidgetWrapper {
if let new = newTitle {
title = new
}
if self.label == title {
return
}
self.label = title
guard self._label != title else { return }
self._label = title
DispatchQueue.main.async(execute: {
self.needsDisplay = true
})
}
public func setColorZones(_ zones: colorZones) {
guard self.colorZones != zones else {
return
}
self.colorZones = zones
public func setColorZones(_ newColorZones: colorZones) {
guard self._colorZones != newColorZones else { return }
self._colorZones = newColorZones
DispatchQueue.main.async(execute: {
self.display()
})
@@ -196,20 +191,20 @@ public class Mini: WidgetWrapper {
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Label"),
action: #selector(toggleLabel),
action: #selector(self.toggleLabel),
state: self.labelState
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Color"),
action: #selector(toggleColor),
action: #selector(self.toggleColor),
items: self.colors,
selected: self.colorState.key
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Alignment"),
action: #selector(toggleAlignment),
action: #selector(self.toggleAlignment),
items: Alignments,
selected: self.alignmentState
))
@@ -218,38 +213,25 @@ public class Mini: WidgetWrapper {
}
@objc private func toggleColor(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let key = sender.representedObject as? String else { return }
if let newColor = Color.allCases.first(where: { $0.key == key }) {
self.colorState = newColor
}
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_color", value: key)
self.display()
}
@objc private func toggleLabel(_ 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.labelState = state! == .on ? true : false
self.labelState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_label", value: self.labelState)
self.display()
}
@objc private func toggleAlignment(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let key = sender.representedObject as? String else { return }
if let newAlignment = Alignments.first(where: { $0.key == key }) {
self.alignmentState = newAlignment.key
}
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_alignment", value: key)
self.display()
}

View File

@@ -244,25 +244,13 @@ public class NetworkChart: WidgetWrapper {
}
@objc private func toggleLabel(_ 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.labelState = state! == .on ? true : false
self.labelState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_label", value: self.labelState)
self.display()
}
@objc private func toggleBox(_ 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.boxState = state! == .on ? true : false
self.boxState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_box", value: self.boxState)
if self.frameState {
@@ -275,13 +263,7 @@ public class NetworkChart: WidgetWrapper {
}
@objc private func toggleFrame(_ 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.frameState = state! == .on ? true : false
self.frameState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_frame", value: self.frameState)
if self.boxState {
@@ -294,9 +276,7 @@ public class NetworkChart: WidgetWrapper {
}
@objc private func toggleHistoryCount(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String, let value = Int(key) else {
return
}
guard let key = sender.representedObject as? String, let value = Int(key) else { return }
self.historyCount = value
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_historyCount", value: value)
@@ -305,9 +285,7 @@ public class NetworkChart: WidgetWrapper {
}
@objc private func toggleDownloadColor(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let key = sender.representedObject as? String else { return }
if let newColor = Color.allCases.first(where: { $0.key == key }) {
self.downloadColor = newColor
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_downloadColor", value: newColor.key)
@@ -320,9 +298,7 @@ public class NetworkChart: WidgetWrapper {
}
@objc private func toggleUploadColor(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let key = sender.representedObject as? String else { return }
if let newColor = Color.allCases.first(where: { $0.key == key }) {
self.uploadColor = newColor
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_uploadColor", value: newColor.key)
@@ -335,11 +311,8 @@ public class NetworkChart: WidgetWrapper {
}
@objc private func toggleScale(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let value = Scale.allCases.first(where: { $0.key == key }) else { return }
guard let key = sender.representedObject as? String,
let value = Scale.allCases.first(where: { $0.key == key }) else { return }
self.scaleState = value
self.chart.setScale(value, self.commonScaleState)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_scale", value: key)
@@ -347,14 +320,7 @@ public class NetworkChart: WidgetWrapper {
}
@objc private func toggleCommonScale(_ 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.commonScaleState = state! == .on ? true : false
self.commonScaleState = controlState(sender)
self.chart.setScale(self.scaleState, self.commonScaleState)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_commonScale", value: self.commonScaleState)
self.display()

View File

@@ -110,13 +110,13 @@ public class PieChart: WidgetWrapper {
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Label"),
action: #selector(toggleLabel),
action: #selector(self.toggleLabel),
state: self.labelState
))
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Monochrome accent"),
action: #selector(toggleMonochrome),
action: #selector(self.toggleMonochrome),
state: self.monochromeState
))
@@ -124,14 +124,7 @@ public class PieChart: WidgetWrapper {
}
@objc private func toggleLabel(_ 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.labelState = state! == .on ? true : false
self.labelState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_label", value: self.labelState)
let x = self.labelState ? 6 + Constants.Widget.spacing : 0
@@ -141,14 +134,7 @@ public class PieChart: WidgetWrapper {
}
@objc private func toggleMonochrome(_ 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.monochromeState = state! == .on ? true : false
self.monochromeState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_monochrome", value: self.monochromeState)
}
}

View File

@@ -233,7 +233,7 @@ public class StackWidget: WidgetWrapper {
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Display mode"),
action: #selector(changeDisplayMode),
action: #selector(self.changeDisplayMode),
items: SensorsWidgetMode,
selected: self.modeState.rawValue
))
@@ -241,14 +241,14 @@ public class StackWidget: WidgetWrapper {
if self.title != "Clock" {
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Static width"),
action: #selector(toggleSize),
action: #selector(self.toggleSize),
state: self.fixedSizeState
))
}
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Monospaced font"),
action: #selector(toggleMonospacedFont),
action: #selector(self.toggleMonospacedFont),
state: self.monospacedFontState
))

View File

@@ -92,25 +92,19 @@ public class StateWidget: WidgetWrapper {
}
@objc private func toggleActiveColor(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let key = sender.representedObject as? String else { return }
if let newColor = Color.allCases.first(where: { $0.key == key }) {
self.activeColorState = newColor
}
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_activeColor", value: key)
self.display()
}
@objc private func toggleNonactiveColor(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let key = sender.representedObject as? String else { return }
if let newColor = Color.allCases.first(where: { $0.key == key }) {
self.nonactiveColorState = newColor
}
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_nonactiveColor", value: key)
self.display()
}

View File

@@ -92,13 +92,13 @@ public class Tachometer: WidgetWrapper {
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Label"),
action: #selector(toggleLabel),
action: #selector(self.toggleLabel),
state: self.labelState
))
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Monochrome accent"),
action: #selector(toggleMonochrome),
action: #selector(self.toggleMonochrome),
state: self.monochromeState
))
@@ -106,14 +106,7 @@ public class Tachometer: WidgetWrapper {
}
@objc private func toggleLabel(_ 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.labelState = state! == .on ? true : false
self.labelState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_label", value: self.labelState)
let x = self.labelState ? 6 + Constants.Widget.spacing : 0
@@ -123,14 +116,7 @@ public class Tachometer: WidgetWrapper {
}
@objc private func toggleMonochrome(_ 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.monochromeState = state! == .on ? true : false
self.monochromeState = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_monochrome", value: self.monochromeState)
}
}

View File

@@ -162,10 +162,7 @@ open class Module: Module_p {
// load function which call when app start
public func mount() {
guard self.enabled else {
return
}
guard self.enabled else { return }
self.readers.forEach { (reader: Reader_p) in
reader.initStoreValues(title: self.config.name)
reader.start()

View File

@@ -158,15 +158,15 @@ open class WidgetWrapper: NSView, widget_p {
public var type: widget_t
public var title: String
public var position: Int = -1
public var widthHandler: (() -> Void)? = nil
public var shadowSize: CGSize
internal var queue: DispatchQueue
public init(_ type: widget_t, title: String, frame: NSRect) {
self.type = type
self.title = title
self.shadowSize = frame.size
self.queue = DispatchQueue(label: "eu.exelban.Stats.WidgetWrapper.\(type.rawValue).\(title)")
super.init(frame: frame)
}
@@ -372,6 +372,7 @@ public class MenuBar {
private var moduleName: String
private var menuBarItem: NSStatusItem? = nil
private var active: Bool = false
private var queue: DispatchQueue
private var combinedModules: Bool {
Store.shared.bool(key: "CombinedModules", defaultValue: false)
@@ -394,6 +395,7 @@ public class MenuBar {
init(moduleName: String) {
self.moduleName = moduleName
self.queue = DispatchQueue(label: "eu.exelban.Stats.MenuBar.\(moduleName)")
self.oneView = Store.shared.bool(key: "\(self.moduleName)_oneView", defaultValue: self.oneView)
self.view.identifier = NSUserInterfaceItemIdentifier(rawValue: moduleName)