mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
feat: now few widgets can be enabled for one module
This commit is contained in:
26
ModuleKit/Supporting Files/Assets.xcassets/widget_settings.imageset/Contents.json
vendored
Normal file
26
ModuleKit/Supporting Files/Assets.xcassets/widget_settings.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "baseline_settings_white_18pt_1x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "baseline_settings_white_18pt_2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "baseline_settings_white_18pt_3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 490 B |
Binary file not shown.
|
After Width: | Height: | Size: 851 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -12,7 +12,7 @@
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
|
||||
public class BarChart: Widget {
|
||||
public class BarChart: WidgetWrapper {
|
||||
private var labelState: Bool = true
|
||||
private var boxState: Bool = true
|
||||
private var frameState: Bool = false
|
||||
@@ -26,7 +26,7 @@ public class BarChart: Widget {
|
||||
private var boxSettingsView: NSView? = nil
|
||||
private var frameSettingsView: NSView? = nil
|
||||
|
||||
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
|
||||
public init(title: String, config: NSDictionary?, store: UnsafePointer<Store>?, preview: Bool = false) {
|
||||
var widgetTitle: String = title
|
||||
self.store = store
|
||||
|
||||
@@ -68,7 +68,7 @@ public class BarChart: Widget {
|
||||
y: Constants.Widget.margin.y,
|
||||
width: Constants.Widget.width + (2*Constants.Widget.margin.x),
|
||||
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
|
||||
), preview: preview)
|
||||
))
|
||||
|
||||
self.canDrawConcurrently = true
|
||||
|
||||
@@ -228,13 +228,17 @@ public class BarChart: Widget {
|
||||
|
||||
// MARK: - Settings
|
||||
|
||||
public override func settings(superview: NSView) {
|
||||
public override func settings(width: CGFloat) -> NSView {
|
||||
let rowHeight: CGFloat = 30
|
||||
let settingsNumber: CGFloat = 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)))
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
y: Constants.Settings.margin,
|
||||
width: width - (Constants.Settings.margin*2),
|
||||
height: height
|
||||
))
|
||||
|
||||
view.addSubview(ToggleTitleRow(
|
||||
frame: NSRect(x: 0, y: (rowHeight + Constants.Settings.margin) * 3, width: view.frame.width, height: rowHeight),
|
||||
@@ -267,7 +271,7 @@ public class BarChart: Widget {
|
||||
selected: self.colorState.rawValue
|
||||
))
|
||||
|
||||
superview.addSubview(view)
|
||||
return view
|
||||
}
|
||||
|
||||
@objc private func toggleLabel(_ sender: NSControl) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
|
||||
public class BatterykWidget: Widget {
|
||||
public class BatterykWidget: WidgetWrapper {
|
||||
private var additional: String = "none"
|
||||
private var timeFormat: String = "short"
|
||||
private var iconState: Bool = true
|
||||
@@ -26,7 +26,7 @@ public class BatterykWidget: Widget {
|
||||
private var charging: Bool = false
|
||||
private var ACStatus: Bool = false
|
||||
|
||||
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
|
||||
public init(title: String, config: NSDictionary?, store: UnsafePointer<Store>?, preview: Bool = false) {
|
||||
let widgetTitle: String = title
|
||||
self.store = store
|
||||
|
||||
@@ -35,11 +35,11 @@ public class BatterykWidget: Widget {
|
||||
y: Constants.Widget.margin.y,
|
||||
width: 30 + (2*Constants.Widget.margin.x),
|
||||
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
|
||||
), preview: preview)
|
||||
))
|
||||
|
||||
self.canDrawConcurrently = true
|
||||
|
||||
if self.store != nil {
|
||||
if self.store != nil && !preview {
|
||||
self.additional = store!.pointee.string(key: "\(self.title)_\(self.type.rawValue)_additional", defaultValue: self.additional)
|
||||
self.timeFormat = store!.pointee.string(key: "\(self.title)_timeFormat", defaultValue: self.timeFormat)
|
||||
self.iconState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_icon", defaultValue: self.iconState)
|
||||
@@ -265,16 +265,15 @@ public class BatterykWidget: Widget {
|
||||
|
||||
// MARK: - Settings
|
||||
|
||||
public override func settings(superview: NSView) {
|
||||
public override func settings(width: CGFloat) -> NSView {
|
||||
let rowHeight: CGFloat = 30
|
||||
let height: CGFloat = ((rowHeight + Constants.Settings.margin) * 3) + 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)
|
||||
width: width - (Constants.Settings.margin*2),
|
||||
height: height
|
||||
))
|
||||
|
||||
view.addSubview(SelectRow(
|
||||
@@ -299,7 +298,7 @@ public class BatterykWidget: Widget {
|
||||
state: self.colorState
|
||||
))
|
||||
|
||||
superview.addSubview(view)
|
||||
return view
|
||||
}
|
||||
|
||||
@objc private func toggleAdditional(_ sender: NSMenuItem) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
|
||||
public class LineChart: Widget {
|
||||
public class LineChart: WidgetWrapper {
|
||||
private var labelState: Bool = true
|
||||
private var boxState: Bool = true
|
||||
private var frameState: Bool = false
|
||||
@@ -36,7 +36,7 @@ public class LineChart: Widget {
|
||||
private var boxSettingsView: NSView? = nil
|
||||
private var frameSettingsView: NSView? = nil
|
||||
|
||||
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
|
||||
public init(title: String, config: NSDictionary?, store: UnsafePointer<Store>?, preview: Bool = false) {
|
||||
var widgetTitle: String = title
|
||||
self.store = store
|
||||
if config != nil {
|
||||
@@ -69,7 +69,7 @@ public class LineChart: Widget {
|
||||
y: Constants.Widget.margin.y,
|
||||
width: self.width + (2*Constants.Widget.margin.x),
|
||||
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
|
||||
), preview: preview)
|
||||
))
|
||||
|
||||
self.canDrawConcurrently = true
|
||||
|
||||
@@ -247,13 +247,17 @@ public class LineChart: Widget {
|
||||
|
||||
// MARK: - Settings
|
||||
|
||||
public override func settings(superview: NSView) {
|
||||
public override func settings(width: CGFloat) -> NSView {
|
||||
let rowHeight: CGFloat = 30
|
||||
let settingsNumber: CGFloat = 6
|
||||
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)))
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
y: Constants.Settings.margin,
|
||||
width: width - (Constants.Settings.margin*2),
|
||||
height: height
|
||||
))
|
||||
|
||||
view.addSubview(ToggleTitleRow(
|
||||
frame: NSRect(x: 0, y: (rowHeight + Constants.Settings.margin) * 5, width: view.frame.width, height: rowHeight),
|
||||
@@ -300,7 +304,7 @@ public class LineChart: Widget {
|
||||
state: self.valueColorState
|
||||
))
|
||||
|
||||
superview.addSubview(view)
|
||||
return view
|
||||
}
|
||||
|
||||
@objc private func toggleLabel(_ sender: NSControl) {
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
|
||||
public class MemoryWidget: Widget {
|
||||
public class MemoryWidget: WidgetWrapper {
|
||||
private var orderReversedState: Bool = false
|
||||
private var value: (String, String) = ("0", "0")
|
||||
|
||||
private let store: UnsafePointer<Store>?
|
||||
|
||||
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
|
||||
public init(title: String, config: NSDictionary?, store: UnsafePointer<Store>?, preview: Bool = false) {
|
||||
self.store = store
|
||||
if config != nil {
|
||||
var configuration = config!
|
||||
@@ -42,11 +42,11 @@ public class MemoryWidget: Widget {
|
||||
y: Constants.Widget.margin.y,
|
||||
width: 62,
|
||||
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
|
||||
), preview: preview)
|
||||
))
|
||||
|
||||
self.canDrawConcurrently = true
|
||||
|
||||
if self.store != nil {
|
||||
if self.store != nil && !preview {
|
||||
self.orderReversedState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_orderReversed", defaultValue: self.orderReversedState)
|
||||
}
|
||||
|
||||
@@ -102,12 +102,16 @@ public class MemoryWidget: Widget {
|
||||
})
|
||||
}
|
||||
|
||||
public override func settings(superview: NSView) {
|
||||
public override func settings(width: CGFloat) -> NSView {
|
||||
let rowHeight: CGFloat = 30
|
||||
let height: CGFloat = ((rowHeight + Constants.Settings.margin) * 1) + 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)))
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
y: Constants.Settings.margin,
|
||||
width: width - (Constants.Settings.margin*2),
|
||||
height: height
|
||||
))
|
||||
|
||||
view.addSubview(ToggleTitleRow(
|
||||
frame: NSRect(x: 0, y: (rowHeight + Constants.Settings.margin) * 0, width: view.frame.width, height: rowHeight),
|
||||
@@ -116,7 +120,7 @@ public class MemoryWidget: Widget {
|
||||
state: self.orderReversedState
|
||||
))
|
||||
|
||||
superview.addSubview(view)
|
||||
return view
|
||||
}
|
||||
|
||||
@objc private func toggleOrder(_ sender: NSControl) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
|
||||
public class Mini: Widget {
|
||||
public class Mini: WidgetWrapper {
|
||||
private let store: UnsafePointer<Store>?
|
||||
private let defaultTitle: String
|
||||
|
||||
@@ -34,7 +34,7 @@ public class Mini: Widget {
|
||||
}
|
||||
}
|
||||
|
||||
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
|
||||
public init(title: String, config: NSDictionary?, store: UnsafePointer<Store>?, preview: Bool = false) {
|
||||
self.store = store
|
||||
var widgetTitle: String = title
|
||||
if config != nil {
|
||||
@@ -73,11 +73,11 @@ public class Mini: Widget {
|
||||
y: Constants.Widget.margin.y,
|
||||
width: Constants.Widget.width + (2*Constants.Widget.margin.x),
|
||||
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
|
||||
), preview: preview)
|
||||
))
|
||||
|
||||
self.wantsLayer = true
|
||||
|
||||
if let store = self.store {
|
||||
if let store = self.store, !preview {
|
||||
self.colorState = widget_c(rawValue: store.pointee.string(key: "\(self.title)_\(self.type.rawValue)_color", defaultValue: self.colorState.rawValue)) ?? self.colorState
|
||||
self.labelState = store.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_label", defaultValue: self.labelState)
|
||||
}
|
||||
@@ -169,12 +169,16 @@ public class Mini: Widget {
|
||||
|
||||
// MARK: - Settings
|
||||
|
||||
public override func settings(superview: NSView) {
|
||||
public override func settings(width: CGFloat) -> NSView {
|
||||
let height: CGFloat = 60 + (Constants.Settings.margin*3)
|
||||
let rowHeight: CGFloat = 30
|
||||
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)))
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
y: Constants.Settings.margin,
|
||||
width: width - (Constants.Settings.margin*2),
|
||||
height: height
|
||||
))
|
||||
|
||||
view.addSubview(ToggleTitleRow(
|
||||
frame: NSRect(x: 0, y: rowHeight + Constants.Settings.margin, width: view.frame.width, height: rowHeight),
|
||||
@@ -191,7 +195,7 @@ public class Mini: Widget {
|
||||
selected: self.colorState.rawValue
|
||||
))
|
||||
|
||||
superview.addSubview(view)
|
||||
return view
|
||||
}
|
||||
|
||||
@objc private func toggleColor(_ sender: NSMenuItem) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
|
||||
public class NetworkChart: Widget {
|
||||
public class NetworkChart: WidgetWrapper {
|
||||
private var boxState: Bool = false
|
||||
private var frameState: Bool = false
|
||||
|
||||
@@ -31,7 +31,7 @@ public class NetworkChart: Widget {
|
||||
private var boxSettingsView: NSView? = nil
|
||||
private var frameSettingsView: NSView? = nil
|
||||
|
||||
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
|
||||
public init(title: String, config: NSDictionary?, store: UnsafePointer<Store>?, preview: Bool = false) {
|
||||
var widgetTitle: String = title
|
||||
self.store = store
|
||||
if config != nil {
|
||||
@@ -45,7 +45,7 @@ public class NetworkChart: Widget {
|
||||
y: Constants.Widget.margin.y,
|
||||
width: self.width + (2*Constants.Widget.margin.x),
|
||||
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
|
||||
), preview: preview)
|
||||
))
|
||||
|
||||
self.wantsLayer = true
|
||||
self.canDrawConcurrently = true
|
||||
@@ -119,13 +119,17 @@ public class NetworkChart: Widget {
|
||||
|
||||
// MARK: - Settings
|
||||
|
||||
public override func settings(superview: NSView) {
|
||||
public override func settings(width: CGFloat) -> NSView {
|
||||
let rowHeight: CGFloat = 30
|
||||
let settingsNumber: CGFloat = 2
|
||||
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)))
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
y: Constants.Settings.margin,
|
||||
width: width - (Constants.Settings.margin*2),
|
||||
height: height
|
||||
))
|
||||
|
||||
self.boxSettingsView = ToggleTitleRow(
|
||||
frame: NSRect(x: 0, y: (rowHeight + Constants.Settings.margin) * 1, width: view.frame.width, height: rowHeight),
|
||||
@@ -143,7 +147,7 @@ public class NetworkChart: Widget {
|
||||
)
|
||||
view.addSubview(self.frameSettingsView!)
|
||||
|
||||
superview.addSubview(view)
|
||||
return view
|
||||
}
|
||||
|
||||
@objc private func toggleBox(_ sender: NSControl) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
|
||||
public class PieChart: Widget {
|
||||
public class PieChart: WidgetWrapper {
|
||||
private var labelState: Bool = true
|
||||
|
||||
private let store: UnsafePointer<Store>?
|
||||
@@ -29,7 +29,7 @@ public class PieChart: Widget {
|
||||
|
||||
private let size: CGFloat = Constants.Widget.height - (Constants.Widget.margin.y*2) + (Constants.Widget.margin.x*2)
|
||||
|
||||
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
|
||||
public init(title: String, config: NSDictionary?, store: UnsafePointer<Store>?, preview: Bool = false) {
|
||||
var widgetTitle: String = title
|
||||
self.store = store
|
||||
if config != nil {
|
||||
@@ -43,12 +43,12 @@ public class PieChart: Widget {
|
||||
y: Constants.Widget.margin.y,
|
||||
width: self.size,
|
||||
height: Constants.Widget.height - (Constants.Widget.margin.y*2)
|
||||
), preview: preview)
|
||||
))
|
||||
|
||||
self.wantsLayer = true
|
||||
self.canDrawConcurrently = true
|
||||
|
||||
if let store = self.store {
|
||||
if let store = self.store, !preview {
|
||||
self.labelState = store.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_label", defaultValue: self.labelState)
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class PieChart: Widget {
|
||||
frame = NSRect(x: x, y: 0, width: self.frame.size.height, height: self.frame.size.height)
|
||||
self.chart.frame = frame
|
||||
|
||||
self.setFrameSize(NSSize(width: self.size + x, height: self.frame.size.height))
|
||||
self.setWidth(self.size + x)
|
||||
}
|
||||
|
||||
public func setValue(_ segments: [circle_segment]) {
|
||||
@@ -98,16 +98,15 @@ public class PieChart: Widget {
|
||||
|
||||
// MARK: - Settings
|
||||
|
||||
public override func settings(superview: NSView) {
|
||||
public override func settings(width: CGFloat) -> NSView {
|
||||
let rowHeight: CGFloat = 30
|
||||
let height: CGFloat = ((rowHeight + Constants.Settings.margin) * 1) + 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)
|
||||
width: width - (Constants.Settings.margin*2),
|
||||
height: height
|
||||
))
|
||||
|
||||
view.addSubview(ToggleTitleRow(
|
||||
@@ -117,7 +116,7 @@ public class PieChart: Widget {
|
||||
state: self.labelState
|
||||
))
|
||||
|
||||
superview.addSubview(view)
|
||||
return view
|
||||
}
|
||||
|
||||
@objc private func toggleLabel(_ sender: NSControl) {
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
|
||||
public class SensorsWidget: Widget {
|
||||
public class SensorsWidget: WidgetWrapper {
|
||||
private var modeState: String = "automatic"
|
||||
private let store: UnsafePointer<Store>?
|
||||
|
||||
private var body: CALayer = CALayer()
|
||||
private var values: [KeyValue_t] = []
|
||||
|
||||
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
|
||||
public init(title: String, config: NSDictionary?, store: UnsafePointer<Store>?, preview: Bool = false) {
|
||||
self.store = store
|
||||
if config != nil {
|
||||
var configuration = config!
|
||||
@@ -41,7 +41,7 @@ public class SensorsWidget: Widget {
|
||||
y: Constants.Widget.margin.y,
|
||||
width: Constants.Widget.width,
|
||||
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
|
||||
), preview: preview)
|
||||
))
|
||||
|
||||
self.modeState = store?.pointee.string(key: "\(self.title)_\(self.type.rawValue)_mode", defaultValue: self.modeState) ?? self.modeState
|
||||
|
||||
@@ -212,16 +212,15 @@ public class SensorsWidget: Widget {
|
||||
|
||||
// MARK: - Settings
|
||||
|
||||
public override func settings(superview: NSView) {
|
||||
public override func settings(width: CGFloat) -> NSView {
|
||||
let rowHeight: CGFloat = 30
|
||||
let height: CGFloat = ((rowHeight + Constants.Settings.margin) * 1) + 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)
|
||||
width: width - (Constants.Settings.margin*2),
|
||||
height: height
|
||||
))
|
||||
|
||||
view.addSubview(SelectRow(
|
||||
@@ -232,7 +231,7 @@ public class SensorsWidget: Widget {
|
||||
selected: self.modeState
|
||||
))
|
||||
|
||||
superview.addSubview(view)
|
||||
return view
|
||||
}
|
||||
|
||||
@objc private func changeMode(_ sender: NSMenuItem) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
|
||||
public class SpeedWidget: Widget {
|
||||
public class SpeedWidget: WidgetWrapper {
|
||||
private var icon: String = "dots"
|
||||
private var state: Bool = false
|
||||
private var valueState: Bool = true
|
||||
@@ -29,7 +29,7 @@ public class SpeedWidget: Widget {
|
||||
private let store: UnsafePointer<Store>?
|
||||
private var width: CGFloat = 58
|
||||
|
||||
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
|
||||
public init(title: String, config: NSDictionary?, store: UnsafePointer<Store>?, preview: Bool = false) {
|
||||
let widgetTitle: String = title
|
||||
self.store = store
|
||||
if config != nil {
|
||||
@@ -46,11 +46,11 @@ public class SpeedWidget: Widget {
|
||||
y: Constants.Widget.margin.y,
|
||||
width: width,
|
||||
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
|
||||
), preview: preview)
|
||||
))
|
||||
|
||||
self.canDrawConcurrently = true
|
||||
|
||||
if self.store != nil {
|
||||
if self.store != nil && !preview {
|
||||
self.valueState = store!.pointee.bool(key: "\(self.title)_\(self.type.rawValue)_value", defaultValue: self.valueState)
|
||||
self.icon = store!.pointee.string(key: "\(self.title)_\(self.type.rawValue)_icon", defaultValue: self.baseValue)
|
||||
self.baseValue = store!.pointee.string(key: "\(self.title)_base", defaultValue: self.baseValue)
|
||||
@@ -211,16 +211,15 @@ public class SpeedWidget: Widget {
|
||||
}
|
||||
}
|
||||
|
||||
public override func settings(superview: NSView) {
|
||||
public override func settings(width: CGFloat) -> NSView {
|
||||
let height: CGFloat = 90 + (Constants.Settings.margin*4)
|
||||
let rowHeight: CGFloat = 30
|
||||
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)
|
||||
width: width - (Constants.Settings.margin*2),
|
||||
height: height
|
||||
))
|
||||
|
||||
view.addSubview(SelectRow(
|
||||
@@ -246,7 +245,7 @@ public class SpeedWidget: Widget {
|
||||
state: self.valueState
|
||||
))
|
||||
|
||||
superview.addSubview(view)
|
||||
return view
|
||||
}
|
||||
|
||||
@objc private func toggleValue(_ sender: NSControl) {
|
||||
|
||||
@@ -14,7 +14,6 @@ public protocol Module_p {
|
||||
var available: Bool { get }
|
||||
var enabled: Bool { get }
|
||||
|
||||
var widget: Widget_p? { get }
|
||||
var settings: Settings_p? { get }
|
||||
|
||||
func mount()
|
||||
@@ -73,7 +72,7 @@ open class Module: Module_p {
|
||||
public var available: Bool = false
|
||||
public var enabled: Bool = false
|
||||
|
||||
public var widget: Widget_p? = nil
|
||||
public var widgets: [Widget] = []
|
||||
public var settings: Settings_p? = nil
|
||||
|
||||
private var settingsView: Settings_v? = nil
|
||||
@@ -83,16 +82,6 @@ open class Module: Module_p {
|
||||
private let log: OSLog
|
||||
private var store: UnsafePointer<Store>
|
||||
private var readers: [Reader_p] = []
|
||||
private var menuBarItem: NSStatusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
|
||||
private var activeWidget: widget_t {
|
||||
get {
|
||||
let widgetStr = self.store.pointee.string(key: "\(self.config.name)_widget", defaultValue: self.config.defaultWidget.rawValue)
|
||||
return widget_t.allCases.first{ $0.rawValue == widgetStr } ?? widget_t.unknown
|
||||
}
|
||||
set {}
|
||||
}
|
||||
private var ready: Bool = false
|
||||
private var widgetLoaded: Bool = false
|
||||
|
||||
public init(store: UnsafePointer<Store>, popup: Popup_p?, settings: Settings_v?) {
|
||||
self.config = module_c(in: Bundle(for: type(of: self)).path(forResource: "config", ofType: "plist")!)
|
||||
@@ -103,14 +92,10 @@ open class Module: Module_p {
|
||||
self.popupView = popup
|
||||
self.available = self.isAvailable()
|
||||
self.enabled = self.store.pointee.bool(key: "\(self.config.name)_state", defaultValue: self.config.defaultState)
|
||||
self.menuBarItem.autosaveName = self.config.name
|
||||
self.menuBarItem.isVisible = self.enabled
|
||||
|
||||
if !self.available {
|
||||
os_log(.debug, log: log, "Module is not available")
|
||||
|
||||
self.menuBarItem.length = 0
|
||||
self.menuBarItem.isVisible = false
|
||||
if self.enabled {
|
||||
self.enabled = false
|
||||
self.store.pointee.set(key: "\(self.config.name)_state", value: false)
|
||||
@@ -119,26 +104,23 @@ open class Module: Module_p {
|
||||
return
|
||||
}
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(listenForWidgetSwitch), name: .switchWidget, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(listenForMouseDownInSettings), name: .clickInSettings, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(listenForModuleToggle), name: .toggleModule, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(listenForPopupToggle), name: .togglePopup, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(listenForToggleWidget), name: .toggleWidget, object: nil)
|
||||
|
||||
if self.config.widgetsConfig.count != 0 {
|
||||
self.initWidget()
|
||||
self.initWidgets()
|
||||
} else {
|
||||
os_log(.debug, log: log, "Module started without widget")
|
||||
}
|
||||
|
||||
self.settings = Settings(config: &self.config, enabled: self.enabled, activeWidget: self.widget, moduleSettings: self.settingsView)
|
||||
self.settings = Settings(store: store, config: &self.config, widgets: &self.widgets, enabled: self.enabled, moduleSettings: self.settingsView)
|
||||
self.settings?.toggleCallback = { [weak self] in
|
||||
self?.toggleEnabled()
|
||||
}
|
||||
|
||||
self.popup = PopupWindow(title: self.config.name, view: self.popupView, visibilityCallback: self.visibilityCallback)
|
||||
|
||||
self.menuBarItem.button?.target = self
|
||||
self.menuBarItem.button?.action = #selector(self.togglePopup)
|
||||
self.menuBarItem.button?.sendAction(on: [.leftMouseDown, .rightMouseDown])
|
||||
}
|
||||
|
||||
deinit {
|
||||
@@ -155,6 +137,7 @@ open class Module: Module_p {
|
||||
reader.initStoreValues(title: self.config.name, store: self.store)
|
||||
reader.start()
|
||||
}
|
||||
self.widgets.forEach{ $0.enable() }
|
||||
}
|
||||
|
||||
// disable module
|
||||
@@ -170,7 +153,7 @@ open class Module: Module_p {
|
||||
$0.stop()
|
||||
$0.terminate()
|
||||
}
|
||||
NSStatusBar.system.removeStatusItem(self.menuBarItem)
|
||||
self.widgets.forEach{ $0.disable() }
|
||||
os_log(.debug, log: log, "Module terminated")
|
||||
}
|
||||
|
||||
@@ -187,12 +170,7 @@ open class Module: Module_p {
|
||||
reader.initStoreValues(title: self.config.name, store: self.store)
|
||||
reader.start()
|
||||
}
|
||||
self.menuBarItem.isVisible = true
|
||||
if self.widget != nil {
|
||||
self.loadWidget()
|
||||
} else {
|
||||
self.initWidget()
|
||||
}
|
||||
self.widgets.forEach{ $0.enable() }
|
||||
os_log(.debug, log: log, "Module enabled")
|
||||
}
|
||||
|
||||
@@ -203,7 +181,7 @@ open class Module: Module_p {
|
||||
self.enabled = false
|
||||
self.store.pointee.set(key: "\(self.config.name)_state", value: false)
|
||||
self.readers.forEach{ $0.stop() }
|
||||
self.menuBarItem.isVisible = false
|
||||
self.widgets.forEach{ $0.disable() }
|
||||
self.popup?.setIsVisible(false)
|
||||
os_log(.debug, log: log, "Module disabled")
|
||||
}
|
||||
@@ -223,22 +201,6 @@ open class Module: Module_p {
|
||||
os_log(.debug, log: log, "Reader %s was added", "\(reader.self)")
|
||||
}
|
||||
|
||||
// handler for reader, calls when main reader is ready, and return first value
|
||||
public func readyHandler() {
|
||||
os_log(.debug, log: log, "Reader report readiness")
|
||||
self.ready = true
|
||||
|
||||
if !self.widgetLoaded {
|
||||
self.loadWidget()
|
||||
}
|
||||
}
|
||||
|
||||
// change menu item width
|
||||
public func widgetWidthHandler(_ width: CGFloat) {
|
||||
os_log(.debug, log: log, "Widget %s change width to %.2f", "\(type(of: self.widget!))", width)
|
||||
self.menuBarItem.length = width
|
||||
}
|
||||
|
||||
// replace a popup view
|
||||
public func replacePopup(_ view: Popup_p) {
|
||||
self.popup?.setIsVisible(false)
|
||||
@@ -249,51 +211,15 @@ open class Module: Module_p {
|
||||
// determine if module is available (can be overrided in module)
|
||||
open func isAvailable() -> Bool { return true }
|
||||
|
||||
// setup menu ber item
|
||||
private func loadWidget() {
|
||||
guard self.available && self.enabled && self.ready && self.widget != nil else { return }
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.menuBarItem.length = self.widget!.frame.width
|
||||
self.menuBarItem.button?.subviews.forEach{ $0.removeFromSuperview() }
|
||||
self.menuBarItem.button?.addSubview(self.widget!)
|
||||
self.widgetLoaded = true
|
||||
self.widgetDidSet(self.widget?.type ?? .unknown)
|
||||
}
|
||||
}
|
||||
|
||||
// load the widget and set up. Calls when module init or widget change
|
||||
private func initWidget() {
|
||||
// load the widget and set up. Calls when module init
|
||||
private func initWidgets() {
|
||||
guard self.available else { return }
|
||||
|
||||
self.widget = self.activeWidget.new(module: 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)")
|
||||
return
|
||||
self.config.availableWidgets.forEach { (widgetType: widget_t) in
|
||||
if let widget = widgetType.new(module: self.config.name, config: self.config.widgetsConfig, store: self.store) {
|
||||
self.widgets.append(widget)
|
||||
}
|
||||
}
|
||||
os_log(.debug, log: log, "Successfully initialize widget: %s", "\(String(describing: self.widget!))")
|
||||
|
||||
self.widget?.widthHandler = { [weak self] value in
|
||||
self?.widgetWidthHandler(value)
|
||||
}
|
||||
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
self.readers.forEach{ $0.read() }
|
||||
}
|
||||
|
||||
if let mainReader = self.readers.first(where: { !$0.optional }) {
|
||||
self.widget?.setValues(mainReader.getHistory())
|
||||
}
|
||||
|
||||
if self.ready && self.enabled {
|
||||
self.menuBarItem.length = self.widget!.frame.width
|
||||
self.menuBarItem.button?.subviews.forEach{ $0.removeFromSuperview() }
|
||||
self.menuBarItem.button?.addSubview(self.widget!)
|
||||
self.widgetLoaded = true
|
||||
}
|
||||
|
||||
self.settings?.setActiveWidget(self.widget)
|
||||
}
|
||||
|
||||
// call after widget set up
|
||||
@@ -312,25 +238,26 @@ open class Module: Module_p {
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func togglePopup(_ sender: Any) {
|
||||
let openedWindows = NSApplication.shared.windows.filter{ $0 is NSPanel }
|
||||
openedWindows.forEach{ $0.setIsVisible(false) }
|
||||
|
||||
guard let popup = self.popup else {
|
||||
@objc private func listenForPopupToggle(_ notification: Notification) {
|
||||
guard let popup = self.popup,
|
||||
let name = notification.userInfo?["module"] as? String,
|
||||
let buttonOrigin = notification.userInfo?["origin"] as? CGPoint,
|
||||
let buttonCenter = notification.userInfo?["center"] as? CGFloat,
|
||||
self.config.name == name else {
|
||||
return
|
||||
}
|
||||
|
||||
let openedWindows = NSApplication.shared.windows.filter{ $0 is NSPanel }
|
||||
openedWindows.forEach{ $0.setIsVisible(false) }
|
||||
|
||||
if popup.occlusionState.rawValue == 8192 {
|
||||
NSApplication.shared.activate(ignoringOtherApps: true)
|
||||
|
||||
popup.contentView?.invalidateIntrinsicContentSize()
|
||||
|
||||
let buttonOrigin = self.menuBarItem.button?.window?.frame.origin
|
||||
let buttonCenter = (self.menuBarItem.button?.window?.frame.width)! / 2
|
||||
|
||||
let windowCenter = popup.contentView!.intrinsicContentSize.width / 2
|
||||
var x = buttonOrigin!.x - windowCenter + buttonCenter
|
||||
let y = buttonOrigin!.y - popup.contentView!.intrinsicContentSize.height - 3
|
||||
var x = buttonOrigin.x - windowCenter + buttonCenter
|
||||
let y = buttonOrigin.y - popup.contentView!.intrinsicContentSize.height - 3
|
||||
|
||||
let maxWidth = NSScreen.screens.map{ $0.frame.width }.reduce(0, +)
|
||||
if x + popup.contentView!.intrinsicContentSize.width > maxWidth {
|
||||
@@ -359,25 +286,25 @@ open class Module: Module_p {
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func listenForWidgetSwitch(_ notification: Notification) {
|
||||
if let moduleName = notification.userInfo?["module"] as? String {
|
||||
if let widgetName = notification.userInfo?["widget"] as? String {
|
||||
if moduleName == self.config.name {
|
||||
if let widgetType = widget_t.allCases.first(where: { $0.rawValue == widgetName }) {
|
||||
self.activeWidget = widgetType
|
||||
self.store.pointee.set(key: "\(self.config.name)_widget", value: widgetType.rawValue)
|
||||
self.initWidget()
|
||||
self.widgetDidSet(widgetType)
|
||||
os_log(.debug, log: log, "Widget is changed to: %s", "\(widgetName)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func listenForMouseDownInSettings(_ notification: Notification) {
|
||||
if let popup = self.popup, popup.isVisible {
|
||||
self.popup?.setIsVisible(false)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func listenForToggleWidget(_ notification: Notification) {
|
||||
guard let name = notification.userInfo?["module"] as? String, name == self.config.name else {
|
||||
return
|
||||
}
|
||||
let count = self.widgets.filter({ $0.isActive }).count
|
||||
var state = self.enabled
|
||||
|
||||
if count == 0 && self.enabled {
|
||||
state = false
|
||||
} else if count != 0 && !self.enabled {
|
||||
state = true
|
||||
}
|
||||
|
||||
NotificationCenter.default.post(name: .toggleModule, object: nil, userInfo: ["module": self.config.name, "state": state])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,53 +14,50 @@ import StatsKit
|
||||
|
||||
public protocol Settings_p: NSView {
|
||||
var toggleCallback: () -> () { get set }
|
||||
func setActiveWidget(_ widget: Widget_p?)
|
||||
}
|
||||
|
||||
public protocol Settings_v: NSView {
|
||||
var callback: (() -> Void) { get set }
|
||||
func load(widget: widget_t)
|
||||
func load(widgets: [widget_t])
|
||||
}
|
||||
|
||||
open class Settings: NSView, Settings_p {
|
||||
public var toggleCallback: () -> () = {}
|
||||
|
||||
private let headerHeight: CGFloat = 42
|
||||
private var widgetSelectorHeight: CGFloat = Constants.Widget.height + (Constants.Settings.margin*2)
|
||||
|
||||
private var settingsView: NSView = NSView()
|
||||
|
||||
private var widgetSelectorView: NSView? = nil
|
||||
private var widgetSettingsView: NSView? = nil
|
||||
private var moduleSettingsView: NSView? = nil
|
||||
|
||||
private var config: UnsafePointer<module_c>
|
||||
private var activeWidget: Widget_p?
|
||||
private var store: UnsafePointer<Store>
|
||||
private var widgets: UnsafeMutablePointer<[Widget]>
|
||||
|
||||
private var activeWidget: Widget? {
|
||||
get {
|
||||
return self.widgets.pointee.first{ $0.isActive }
|
||||
}
|
||||
}
|
||||
|
||||
private var moduleSettings: Settings_v?
|
||||
private var enableControl: NSControl?
|
||||
private var container: ScrollableStackView?
|
||||
private var widgetSettings: widget_t?
|
||||
private var moduleSettingsContainer: NSView?
|
||||
|
||||
init(config: UnsafePointer<module_c>, enabled: Bool, activeWidget: Widget_p?, moduleSettings: Settings_v?) {
|
||||
init(store: UnsafePointer<Store>, config: UnsafePointer<module_c>, widgets: UnsafeMutablePointer<[Widget]>, enabled: Bool, moduleSettings: Settings_v?) {
|
||||
self.store = store
|
||||
self.config = config
|
||||
self.activeWidget = activeWidget
|
||||
self.widgets = widgets
|
||||
self.moduleSettings = moduleSettings
|
||||
|
||||
super.init(frame: NSRect(x: 0, y: 0, width: Constants.Settings.width, height: Constants.Settings.height))
|
||||
|
||||
self.wantsLayer = true
|
||||
self.appearance = NSAppearance(named: .aqua)
|
||||
self.layer?.backgroundColor = NSColor(hexString: "#ececec").cgColor
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(externalModuleToggle), name: .toggleModule, object: nil)
|
||||
|
||||
self.addHeader(state: enabled)
|
||||
self.addSettings()
|
||||
|
||||
self.addWidgetSelector()
|
||||
self.addWidgetSettings()
|
||||
|
||||
if self.moduleSettings != nil {
|
||||
self.moduleSettings?.load(widget: self.activeWidget?.type ?? .unknown)
|
||||
self.addModuleSettings()
|
||||
}
|
||||
self.addSubview(self.header(state: enabled))
|
||||
self.addSubview(self.body())
|
||||
}
|
||||
|
||||
deinit {
|
||||
@@ -71,157 +68,9 @@ open class Settings: NSView, Settings_p {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func addSettings() {
|
||||
let view: NSScrollView = NSScrollView(frame: NSRect(
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: self.frame.width,
|
||||
height: Constants.Settings.height - self.headerHeight
|
||||
))
|
||||
view.wantsLayer = true
|
||||
view.backgroundColor = NSColor(hexString: "#ececec")
|
||||
|
||||
view.translatesAutoresizingMaskIntoConstraints = true
|
||||
view.borderType = .noBorder
|
||||
view.hasVerticalScroller = true
|
||||
view.hasHorizontalScroller = false
|
||||
view.autohidesScrollers = true
|
||||
view.horizontalScrollElasticity = .none
|
||||
|
||||
let settings: NSView = FlippedView(frame: NSRect(x: 0, y: 0, width: view.frame.width, height: 0))
|
||||
settings.wantsLayer = true
|
||||
settings.layer?.backgroundColor = NSColor(hexString: "#ececec").cgColor
|
||||
|
||||
view.documentView = settings
|
||||
|
||||
self.addSubview(view)
|
||||
self.settingsView = settings
|
||||
}
|
||||
// MARK: - Views
|
||||
|
||||
private func addWidgetSelector() {
|
||||
if self.config.pointee.availableWidgets.count == 0 {
|
||||
self.widgetSelectorHeight = 0
|
||||
return
|
||||
}
|
||||
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x : Constants.Settings.margin,
|
||||
y: Constants.Settings.margin,
|
||||
width: self.settingsView.frame.width - (Constants.Settings.margin*2),
|
||||
height: self.widgetSelectorHeight
|
||||
))
|
||||
view.wantsLayer = true
|
||||
view.layer?.backgroundColor = .white
|
||||
view.layer!.cornerRadius = 3
|
||||
|
||||
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 = widgetType.new(module: self.config.pointee.name, config: self.config.pointee.widgetsConfig, store: nil, preview: true) {
|
||||
let preview = WidgetPreview(
|
||||
frame: NSRect(
|
||||
x: x,
|
||||
y: Constants.Settings.margin,
|
||||
width: widget.frame.width + (Constants.Widget.spacing*2),
|
||||
height: self.widgetSelectorHeight - (Constants.Settings.margin*2)
|
||||
),
|
||||
title: self.config.pointee.name,
|
||||
widget: widget,
|
||||
state: self.activeWidget?.type == widgetType
|
||||
)
|
||||
preview.widthCallback = { [weak self] in
|
||||
self?.recalculateWidgetSelectorOptionsWidth()
|
||||
}
|
||||
view.addSubview(preview)
|
||||
x += preview.frame.width + Constants.Settings.margin
|
||||
}
|
||||
}
|
||||
|
||||
self.settingsView.addSubview(view)
|
||||
self.widgetSelectorView = view
|
||||
self.resize()
|
||||
}
|
||||
|
||||
private func addWidgetSettings() {
|
||||
if self.activeWidget == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var y: CGFloat = Constants.Settings.margin
|
||||
if self.widgetSelectorView != nil {
|
||||
y += self.widgetSelectorView!.frame.height + Constants.Settings.margin
|
||||
}
|
||||
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
y: y,
|
||||
width: self.settingsView.frame.width - (Constants.Settings.margin*2),
|
||||
height: 0
|
||||
))
|
||||
view.wantsLayer = true
|
||||
view.layer?.backgroundColor = .white
|
||||
view.layer!.cornerRadius = 3
|
||||
|
||||
self.activeWidget?.settings(superview: view)
|
||||
|
||||
if view.frame.height != 0 {
|
||||
self.settingsView.addSubview(view)
|
||||
self.widgetSettingsView = view
|
||||
self.resize()
|
||||
}
|
||||
}
|
||||
|
||||
private func addModuleSettings() {
|
||||
if self.moduleSettings == nil || self.moduleSettings?.frame.height == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var y: CGFloat = Constants.Settings.margin
|
||||
if self.widgetSelectorView != nil {
|
||||
y += self.widgetSelectorView!.frame.height + Constants.Settings.margin
|
||||
}
|
||||
if self.widgetSettingsView != nil {
|
||||
y += self.widgetSettingsView!.frame.height + Constants.Settings.margin
|
||||
}
|
||||
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
y: y,
|
||||
width: self.settingsView.frame.width - (Constants.Settings.margin*2),
|
||||
height: self.moduleSettings?.frame.height ?? 0
|
||||
))
|
||||
view.wantsLayer = true
|
||||
view.layer?.backgroundColor = .white
|
||||
view.layer!.cornerRadius = 3
|
||||
|
||||
view.addSubview(self.moduleSettings!)
|
||||
|
||||
self.settingsView.addSubview(view)
|
||||
self.moduleSettingsView = view
|
||||
self.resize()
|
||||
}
|
||||
|
||||
private func resize() {
|
||||
var height: CGFloat = Constants.Settings.margin
|
||||
|
||||
self.settingsView.subviews.forEach({ (v: NSView) in
|
||||
height += v.frame.height + Constants.Settings.margin
|
||||
})
|
||||
|
||||
if self.settingsView.frame.height != height {
|
||||
self.settingsView.setFrameSize(NSSize(width: self.settingsView.frame.width, height: height))
|
||||
}
|
||||
}
|
||||
|
||||
private func recalculateWidgetSelectorOptionsWidth() {
|
||||
var x: CGFloat = Constants.Settings.margin
|
||||
self.widgetSelectorView?.subviews.forEach({ (v: NSView) in
|
||||
v.setFrameOrigin(NSPoint(x: x, y: v.frame.origin.y))
|
||||
x += v.frame.width + Constants.Settings.margin
|
||||
})
|
||||
}
|
||||
|
||||
private func addHeader(state: Bool) {
|
||||
private func header(state: Bool) -> NSView {
|
||||
let view: NSView = NSView(frame: NSRect(x: 0, y: self.frame.height - self.headerHeight, width: self.frame.width, height: self.headerHeight))
|
||||
view.wantsLayer = true
|
||||
|
||||
@@ -265,16 +114,134 @@ open class Settings: NSView, Settings_p {
|
||||
view.addSubview(titleView)
|
||||
view.addSubview(toggle)
|
||||
view.addSubview(line)
|
||||
|
||||
self.enableControl = toggle
|
||||
self.addSubview(view)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
@objc func toggleEnable(_ sender: Any) {
|
||||
private func body() -> NSView {
|
||||
let view = ScrollableStackView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: Constants.Settings.height - self.headerHeight))
|
||||
view.stackView.edgeInsets = NSEdgeInsets(
|
||||
top: Constants.Settings.margin,
|
||||
left: Constants.Settings.margin,
|
||||
bottom: Constants.Settings.margin,
|
||||
right: Constants.Settings.margin
|
||||
)
|
||||
view.stackView.spacing = Constants.Settings.margin
|
||||
|
||||
view.wantsLayer = true
|
||||
view.layer?.backgroundColor = NSColor(hexString: "#ececec").cgColor
|
||||
self.container = view
|
||||
|
||||
self.initWidgetSelector()
|
||||
self.initModuleSettings()
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
private func initWidgetSelector() {
|
||||
let container: NSView = NSView(frame: NSRect(x: 0, y: 0, width: 0, height: Constants.Widget.height + (Constants.Settings.margin*2)))
|
||||
container.wantsLayer = true
|
||||
container.layer?.backgroundColor = .white
|
||||
container.layer?.cornerRadius = 3
|
||||
|
||||
let view: NSStackView = NSStackView()
|
||||
view.orientation = .horizontal
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.edgeInsets = NSEdgeInsets(
|
||||
top: Constants.Settings.margin,
|
||||
left: Constants.Settings.margin,
|
||||
bottom: Constants.Settings.margin,
|
||||
right: Constants.Settings.margin
|
||||
)
|
||||
view.spacing = Constants.Settings.margin
|
||||
|
||||
for i in 0...self.widgets.pointee.count - 1 {
|
||||
let preview = WidgetPreview(&self.widgets.pointee[i])
|
||||
preview.settingsCallback = { [weak self] value in
|
||||
self?.toggleSettings(value)
|
||||
}
|
||||
preview.stateCallback = { [weak self] in
|
||||
self?.widgetStateCallback()
|
||||
}
|
||||
view.addArrangedSubview(preview)
|
||||
}
|
||||
|
||||
container.addSubview(view)
|
||||
|
||||
if let view = self.container {
|
||||
view.stackView.addArrangedSubview(container)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
container.heightAnchor.constraint(equalToConstant: container.frame.height),
|
||||
view.heightAnchor.constraint(equalTo: container.heightAnchor),
|
||||
])
|
||||
}
|
||||
|
||||
private func initModuleSettings() {
|
||||
guard let settingsView = self.moduleSettings else {
|
||||
return
|
||||
}
|
||||
|
||||
let container: NSView = NSView(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
|
||||
container.wantsLayer = true
|
||||
container.layer?.backgroundColor = .white
|
||||
container.layer?.cornerRadius = 3
|
||||
self.moduleSettingsContainer = container
|
||||
|
||||
self.moduleSettings?.load(widgets: self.widgets.pointee.filter{ $0.isActive }.map{ $0.type })
|
||||
|
||||
container.addSubview(settingsView)
|
||||
if let view = self.container {
|
||||
view.stackView.addArrangedSubview(container)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
container.heightAnchor.constraint(equalTo: settingsView.heightAnchor),
|
||||
])
|
||||
}
|
||||
|
||||
// MARK: - helpers
|
||||
|
||||
private func toggleSettings(_ type: widget_t) {
|
||||
guard let widget = self.widgets.pointee.first(where: { $0.type == type }) else {
|
||||
return
|
||||
}
|
||||
|
||||
let container: NSView = NSView()
|
||||
container.wantsLayer = true
|
||||
container.layer?.backgroundColor = .white
|
||||
container.layer?.cornerRadius = 3
|
||||
|
||||
let width: CGFloat = (self.container?.clipView.bounds.width ?? self.frame.width) - (Constants.Settings.margin*2)
|
||||
let settingsView = widget.item.settings(width: width)
|
||||
container.addSubview(settingsView)
|
||||
|
||||
if let view = self.container {
|
||||
if self.widgetSettings == nil {
|
||||
view.stackView.insertArrangedSubview(container, at: 1)
|
||||
self.widgetSettings = type
|
||||
} else if self.widgetSettings != nil && self.widgetSettings == type {
|
||||
view.stackView.arrangedSubviews[1].removeFromSuperview()
|
||||
self.widgetSettings = nil
|
||||
} else {
|
||||
view.stackView.arrangedSubviews[1].removeFromSuperview()
|
||||
self.widgetSettings = type
|
||||
view.stackView.insertArrangedSubview(container, at: 1)
|
||||
}
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
container.heightAnchor.constraint(equalTo: settingsView.heightAnchor),
|
||||
])
|
||||
}
|
||||
|
||||
@objc private func toggleEnable(_ sender: Any) {
|
||||
self.toggleCallback()
|
||||
}
|
||||
|
||||
@objc func externalModuleToggle(_ notification: Notification) {
|
||||
@objc private func externalModuleToggle(_ notification: Notification) {
|
||||
if let name = notification.userInfo?["module"] as? String {
|
||||
if name == self.config.pointee.name {
|
||||
if let state = notification.userInfo?["state"] as? Bool {
|
||||
@@ -284,113 +251,140 @@ open class Settings: NSView, Settings_p {
|
||||
}
|
||||
}
|
||||
|
||||
public func setActiveWidget(_ widget: Widget_p?) {
|
||||
self.activeWidget = widget
|
||||
|
||||
self.widgetSettingsView?.removeFromSuperview()
|
||||
self.moduleSettingsView?.removeFromSuperview()
|
||||
|
||||
self.widgetSettingsView = nil
|
||||
self.addWidgetSettings()
|
||||
|
||||
if self.moduleSettings != nil {
|
||||
self.moduleSettings?.load(widget: self.activeWidget?.type ?? .unknown)
|
||||
self.addModuleSettings()
|
||||
@objc private func widgetStateCallback() {
|
||||
guard let container = self.moduleSettingsContainer, let settingsView = self.moduleSettings else {
|
||||
return
|
||||
}
|
||||
|
||||
container.subviews.forEach{ $0.removeFromSuperview() }
|
||||
settingsView.load(widgets: self.widgets.pointee.filter{ $0.isActive }.map{ $0.type })
|
||||
self.moduleSettingsContainer?.addSubview(settingsView)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
container.heightAnchor.constraint(equalTo: settingsView.heightAnchor),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
open class FlippedView: NSView {
|
||||
open override var isFlipped: Bool { true }
|
||||
}
|
||||
|
||||
class WidgetPreview: NSView {
|
||||
private let type: widget_t
|
||||
private var state: Bool
|
||||
private let title: String
|
||||
internal class WidgetPreview: NSStackView {
|
||||
public var settingsCallback: (widget_t) -> Void = {_ in }
|
||||
public var stateCallback: () -> Void = {}
|
||||
|
||||
public var widthCallback: () -> Void = {}
|
||||
private var widget: UnsafeMutablePointer<Widget>
|
||||
private var size: CGFloat = Constants.Widget.height
|
||||
|
||||
public init(frame: NSRect, title: String, widget: Widget_p, state: Bool) {
|
||||
self.type = widget.type
|
||||
self.state = state
|
||||
self.title = title
|
||||
public init(_ widget: UnsafeMutablePointer<Widget>) {
|
||||
self.widget = widget
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(maybeActivate), name: .switchWidget, object: nil)
|
||||
super.init(frame: NSRect(
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: widget.pointee.preview.frame.width + self.size + (Constants.Widget.spacing*2),
|
||||
height: self.size
|
||||
))
|
||||
|
||||
self.wantsLayer = true
|
||||
self.layer?.cornerRadius = 2
|
||||
self.layer?.borderColor = self.state ? NSColor.systemBlue.cgColor : NSColor(hexString: "#dddddd").cgColor
|
||||
self.layer?.borderColor = self.widget.pointee.isActive ? NSColor.systemBlue.cgColor : NSColor(hexString: "#dddddd").cgColor
|
||||
self.layer?.borderWidth = 1
|
||||
self.toolTip = LocalizedString("Select widget", widget.pointee.type.name())
|
||||
|
||||
self.toolTip = LocalizedString("Select widget", widget.type.name())
|
||||
self.orientation = .horizontal
|
||||
self.distribution = .fillProportionally
|
||||
self.spacing = 0
|
||||
|
||||
let container: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Widget.spacing,
|
||||
y: 0,
|
||||
width: frame.width - (Constants.Widget.spacing*2),
|
||||
height: frame.height
|
||||
width: widget.pointee.preview.frame.width,
|
||||
height: self.frame.height
|
||||
))
|
||||
container.wantsLayer = true
|
||||
container.addSubview(widget)
|
||||
container.addSubview(widget.pointee.preview)
|
||||
|
||||
self.addSubview(container)
|
||||
self.addArrangedSubview(container)
|
||||
self.addArrangedSubview(self.separator())
|
||||
self.addArrangedSubview(self.button())
|
||||
|
||||
widget.widthHandler = { [weak self] value in
|
||||
self?.removeTrackingArea((self?.trackingAreas.first)!)
|
||||
let newWidth = value + (Constants.Widget.spacing*2)
|
||||
|
||||
let rect = NSRect(x: 0, y: 0, width: newWidth, height: self!.frame.height)
|
||||
let trackingArea = NSTrackingArea(rect: rect, options: [NSTrackingArea.Options.activeAlways, NSTrackingArea.Options.mouseEnteredAndExited, NSTrackingArea.Options.activeInActiveApp], owner: self, userInfo: ["menu": self!.type])
|
||||
self?.addTrackingArea(trackingArea)
|
||||
|
||||
DispatchQueue.main.async(execute: {
|
||||
container.setFrameSize(NSSize(width: value, height: container.frame.height))
|
||||
self?.setFrameSize(NSSize(width: newWidth, height: self?.frame.height ?? Constants.Widget.height))
|
||||
self?.widthCallback()
|
||||
widget.pointee.preview.widthHandler = { [weak self] value in
|
||||
self?.trackingAreas.forEach({ (area: NSTrackingArea) in
|
||||
self?.removeTrackingArea(area)
|
||||
})
|
||||
|
||||
let rect = NSRect(x: Constants.Widget.spacing, y: 0, width: value, height: self!.frame.height)
|
||||
let trackingArea = NSTrackingArea(rect: rect, options: [NSTrackingArea.Options.activeAlways, NSTrackingArea.Options.mouseEnteredAndExited, NSTrackingArea.Options.activeInActiveApp], owner: self, userInfo: nil)
|
||||
self?.addTrackingArea(trackingArea)
|
||||
}
|
||||
|
||||
let rect = NSRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
|
||||
let trackingArea = NSTrackingArea(rect: rect, options: [NSTrackingArea.Options.activeAlways, NSTrackingArea.Options.mouseEnteredAndExited, NSTrackingArea.Options.activeInActiveApp], owner: self, userInfo: ["menu": self.type])
|
||||
self.addTrackingArea(trackingArea)
|
||||
let rect = NSRect(x: Constants.Widget.spacing, y: 0, width: container.frame.width, height: self.frame.height)
|
||||
self.addTrackingArea(NSTrackingArea(
|
||||
rect: rect,
|
||||
options: [NSTrackingArea.Options.activeAlways, NSTrackingArea.Options.mouseEnteredAndExited, NSTrackingArea.Options.activeInActiveApp],
|
||||
owner: self,
|
||||
userInfo: nil
|
||||
))
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
self.widthAnchor.constraint(equalTo: self.widget.pointee.preview.widthAnchor, constant: self.size),
|
||||
self.heightAnchor.constraint(equalToConstant: self.size)
|
||||
])
|
||||
}
|
||||
|
||||
private func button() -> NSView {
|
||||
let button = NSButton(frame: NSRect(x: 0, y: 0, width: self.size, height: self.size))
|
||||
button.title = LocalizedString("Open widget settings")
|
||||
button.toolTip = LocalizedString("Open widget settings")
|
||||
button.bezelStyle = .regularSquare
|
||||
if let image = Bundle(for: type(of: self)).image(forResource: "widget_settings") {
|
||||
button.image = image
|
||||
}
|
||||
button.imageScaling = .scaleProportionallyDown
|
||||
button.contentTintColor = .lightGray
|
||||
button.isBordered = false
|
||||
button.action = #selector(self.toggleSettings)
|
||||
button.target = self
|
||||
button.focusRingType = .none
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
button.widthAnchor.constraint(equalToConstant: button.frame.width),
|
||||
])
|
||||
|
||||
return button
|
||||
}
|
||||
|
||||
private func separator() -> NSView {
|
||||
let separator = NSView()
|
||||
separator.widthAnchor.constraint(equalToConstant: 1).isActive = true
|
||||
separator.wantsLayer = true
|
||||
separator.layer?.backgroundColor = NSColor(hexString: "#dddddd").cgColor
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
separator.heightAnchor.constraint(equalToConstant: self.size),
|
||||
])
|
||||
|
||||
return separator
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@objc private func toggleSettings() {
|
||||
self.settingsCallback(self.widget.pointee.type)
|
||||
}
|
||||
|
||||
override func mouseEntered(with: NSEvent) {
|
||||
self.layer?.borderColor = NSColor.systemBlue.cgColor
|
||||
NSCursor.pointingHand.set()
|
||||
}
|
||||
|
||||
override func mouseExited(with: NSEvent) {
|
||||
self.layer?.borderColor = self.state ? NSColor.systemBlue.cgColor : NSColor.tertiaryLabelColor.cgColor
|
||||
self.layer?.borderColor = self.widget.pointee.isActive ? NSColor.systemBlue.cgColor : NSColor.tertiaryLabelColor.cgColor
|
||||
NSCursor.arrow.set()
|
||||
}
|
||||
|
||||
override func mouseDown(with: NSEvent) {
|
||||
if !self.state {
|
||||
NotificationCenter.default.post(name: .switchWidget, object: nil, userInfo: ["module": self.title, "widget": self.type.rawValue])
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func maybeActivate(_ notification: Notification) {
|
||||
if let moduleName = notification.userInfo?["module"] as? String {
|
||||
if moduleName == self.title {
|
||||
if let widgetName = notification.userInfo?["widget"] as? String {
|
||||
if widgetName == self.type.rawValue {
|
||||
self.layer?.borderColor = NSColor.systemBlue.cgColor
|
||||
self.state = true
|
||||
} else {
|
||||
self.layer?.borderColor = NSColor.tertiaryLabelColor.cgColor
|
||||
self.state = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.widget.pointee.toggle()
|
||||
self.stateCallback()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import os.log
|
||||
import StatsKit
|
||||
|
||||
public enum widget_t: String {
|
||||
@@ -24,37 +25,64 @@ public enum widget_t: String {
|
||||
case sensors = "sensors"
|
||||
case memory = "memory"
|
||||
|
||||
public func new(module: String, config: NSDictionary?, store: UnsafePointer<Store>?, preview: Bool = false) -> Widget_p? {
|
||||
var widget: Widget_p? = nil
|
||||
public func new(module: String, config: NSDictionary?, store: UnsafePointer<Store>?) -> Widget? {
|
||||
var widget: Widget? = nil
|
||||
let widgetConfig: NSDictionary? = config?[self.rawValue] as? NSDictionary
|
||||
|
||||
switch self {
|
||||
case .mini:
|
||||
widget = Mini(preview: preview, title: module, config: widgetConfig, store: store)
|
||||
widget = Widget(self, module: module,
|
||||
preview: Mini(title: module, config: widgetConfig, store: store, preview: true),
|
||||
item: Mini(title: module, config: widgetConfig, store: store)
|
||||
)
|
||||
break
|
||||
case .lineChart:
|
||||
widget = LineChart(preview: preview, title: module, config: widgetConfig, store: store)
|
||||
widget = Widget(self, module: module,
|
||||
preview: LineChart(title: module, config: widgetConfig, store: store, preview: true),
|
||||
item: LineChart(title: module, config: widgetConfig, store: store)
|
||||
)
|
||||
break
|
||||
case .barChart:
|
||||
widget = BarChart(preview: preview, title: module, config: widgetConfig, store: store)
|
||||
widget = Widget(self, module: module,
|
||||
preview: BarChart(title: module, config: widgetConfig, store: store, preview: true),
|
||||
item: BarChart(title: module, config: widgetConfig, store: store)
|
||||
)
|
||||
break
|
||||
case .pieChart:
|
||||
widget = PieChart(preview: preview, title: module, config: widgetConfig, store: store)
|
||||
widget = Widget(self, module: module,
|
||||
preview: PieChart(title: module, config: widgetConfig, store: store, preview: true),
|
||||
item: PieChart(title: module, config: widgetConfig, store: store)
|
||||
)
|
||||
break
|
||||
case .networkChart:
|
||||
widget = NetworkChart(preview: preview, title: module, config: widgetConfig, store: store)
|
||||
widget = Widget(self, module: module,
|
||||
preview: NetworkChart(title: module, config: widgetConfig, store: store, preview: true),
|
||||
item: NetworkChart(title: module, config: widgetConfig, store: store)
|
||||
)
|
||||
break
|
||||
case .speed:
|
||||
widget = SpeedWidget(preview: preview, title: module, config: widgetConfig, store: store)
|
||||
widget = Widget(self, module: module,
|
||||
preview: SpeedWidget(title: module, config: widgetConfig, store: store, preview: true),
|
||||
item: SpeedWidget(title: module, config: widgetConfig, store: store)
|
||||
)
|
||||
break
|
||||
case .battery:
|
||||
widget = BatterykWidget(preview: preview, title: module, config: widgetConfig, store: store)
|
||||
widget = Widget(self, module: module,
|
||||
preview: BatterykWidget(title: module, config: widgetConfig, store: store, preview: true),
|
||||
item: BatterykWidget(title: module, config: widgetConfig, store: store)
|
||||
)
|
||||
break
|
||||
case .sensors:
|
||||
widget = SensorsWidget(preview: preview, title: module, config: widgetConfig, store: store)
|
||||
widget = Widget(self, module: module,
|
||||
preview: SensorsWidget(title: module, config: widgetConfig, store: store, preview: true),
|
||||
item: SensorsWidget(title: module, config: widgetConfig, store: store)
|
||||
)
|
||||
break
|
||||
case .memory:
|
||||
widget = MemoryWidget(preview: preview, title: module, config: widgetConfig, store: store)
|
||||
widget = Widget(self, module: module,
|
||||
preview: MemoryWidget(title: module, config: widgetConfig, store: store, preview: true),
|
||||
item: MemoryWidget(title: module, config: widgetConfig, store: store)
|
||||
)
|
||||
break
|
||||
default: break
|
||||
}
|
||||
@@ -79,27 +107,25 @@ public enum widget_t: String {
|
||||
}
|
||||
extension widget_t: CaseIterable {}
|
||||
|
||||
public protocol Widget_p: NSView {
|
||||
public protocol widget_p: NSView {
|
||||
var type: widget_t { get }
|
||||
var title: String { get }
|
||||
|
||||
var widthHandler: ((CGFloat) -> Void)? { get set }
|
||||
|
||||
func setValues(_ values: [value_t])
|
||||
func settings(superview: NSView)
|
||||
func settings(width: CGFloat) -> NSView
|
||||
}
|
||||
|
||||
open class Widget: NSView, Widget_p {
|
||||
open class WidgetWrapper: NSView, widget_p {
|
||||
public var type: widget_t
|
||||
public var title: String
|
||||
|
||||
public var widthHandler: ((CGFloat) -> Void)? = nil
|
||||
private var widthHandlerRetry: Int8 = 0
|
||||
open override var intrinsicContentSize: CGSize {
|
||||
return CGSize(width: self.frame.size.width, height: self.frame.size.height)
|
||||
}
|
||||
|
||||
public init(_ type: widget_t, title: String, frame: NSRect, preview: Bool) {
|
||||
private var widthHandlerRetry: Int8 = 0
|
||||
|
||||
public init(_ type: widget_t, title: String, frame: NSRect) {
|
||||
self.type = type
|
||||
self.title = title
|
||||
|
||||
@@ -134,6 +160,101 @@ open class Widget: NSView, Widget_p {
|
||||
|
||||
// MARK: - stubs
|
||||
|
||||
open func settings(superview: NSView) {}
|
||||
open func settings(width: CGFloat) -> NSView { return NSView() }
|
||||
open func setValues(_ values: [value_t]) {}
|
||||
}
|
||||
|
||||
public class Widget {
|
||||
public let type: widget_t
|
||||
public let module: String
|
||||
public let preview: widget_p
|
||||
public let item: widget_p
|
||||
|
||||
public var isActive: Bool {
|
||||
get {
|
||||
let arr = Store.shared.string(key: "\(self.module)_widget", defaultValue: "").split(separator: ",")
|
||||
return arr.contains{ $0 == self.type.rawValue }
|
||||
}
|
||||
set {
|
||||
var arr = Store.shared.string(key: "\(self.module)_widget", defaultValue: "").split(separator: ",").map{ String($0) }
|
||||
|
||||
if newValue {
|
||||
arr.append(self.type.rawValue)
|
||||
} else {
|
||||
arr.removeAll{ $0 == self.type.rawValue }
|
||||
}
|
||||
|
||||
Store.shared.set(key: "\(self.module)_widget", value: arr.joined(separator: ","))
|
||||
}
|
||||
}
|
||||
|
||||
private var menuBarItem: NSStatusItem? = nil
|
||||
private let log: OSLog
|
||||
|
||||
public init(_ type: widget_t, module: String, preview: widget_p, item: widget_p) {
|
||||
self.type = type
|
||||
self.module = module
|
||||
self.preview = preview
|
||||
self.item = item
|
||||
self.log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: self.module)
|
||||
|
||||
self.item.widthHandler = { [weak self] value in
|
||||
if let s = self {
|
||||
s.menuBarItem?.length = value
|
||||
os_log(.debug, log: s.log, "Widget %s change width to %.2f", "\(s.type)", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// show item in the menu bar
|
||||
public func enable() {
|
||||
guard self.isActive else {
|
||||
return
|
||||
}
|
||||
|
||||
let item = NSStatusBar.system.statusItem(withLength: self.item.frame.width)
|
||||
item.autosaveName = "\(self.module)_\(self.type.name())"
|
||||
item.isVisible = true
|
||||
item.button?.target = self
|
||||
item.button?.action = #selector(self.togglePopup)
|
||||
item.button?.sendAction(on: [.leftMouseDown, .rightMouseDown])
|
||||
item.button?.addSubview(self.item)
|
||||
|
||||
self.menuBarItem = item
|
||||
|
||||
os_log(.debug, log: log, "Widget %s enabled", self.type.rawValue)
|
||||
}
|
||||
|
||||
// remove item from the menu bar
|
||||
public func disable() {
|
||||
if let item = self.menuBarItem {
|
||||
item.length = 0
|
||||
item.isVisible = false
|
||||
|
||||
os_log(.debug, log: log, "Widget %s disabled", self.type.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
// toggle the widget
|
||||
public func toggle() {
|
||||
self.isActive = !self.isActive
|
||||
|
||||
if !self.isActive {
|
||||
self.disable()
|
||||
} else {
|
||||
self.enable()
|
||||
}
|
||||
|
||||
NotificationCenter.default.post(name: .toggleWidget, object: nil, userInfo: ["module": self.module])
|
||||
}
|
||||
|
||||
@objc private func togglePopup(_ sender: Any) {
|
||||
if let window = self.menuBarItem?.button?.window {
|
||||
NotificationCenter.default.post(name: .togglePopup, object: nil, userInfo: [
|
||||
"module": self.module,
|
||||
"origin": window.frame.origin,
|
||||
"center": window.frame.width/2,
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,9 +76,6 @@ public class Battery: Module {
|
||||
}
|
||||
}
|
||||
|
||||
self.usageReader?.readyCallback = { [unowned self] in
|
||||
self.readyHandler()
|
||||
}
|
||||
self.usageReader?.callbackHandler = { [unowned self] value in
|
||||
self.usageCallback(value)
|
||||
}
|
||||
@@ -103,26 +100,27 @@ public class Battery: Module {
|
||||
return sources.count > 0
|
||||
}
|
||||
|
||||
private func usageCallback(_ value: Battery_Usage?) {
|
||||
if value == nil {
|
||||
private func usageCallback(_ raw: Battery_Usage?) {
|
||||
guard let value = raw else {
|
||||
return
|
||||
}
|
||||
|
||||
self.checkNotification(value: value!)
|
||||
self.popupView.usageCallback(value!)
|
||||
if let widget = self.widget as? Mini {
|
||||
widget.setValue(abs(value!.level))
|
||||
}
|
||||
if let widget = self.widget as? BarChart {
|
||||
widget.setValue([value!.level])
|
||||
}
|
||||
if let widget = self.widget as? BatterykWidget {
|
||||
widget.setValue(
|
||||
percentage: value?.level ?? 0,
|
||||
ACStatus: value?.powerSource != "Battery Power",
|
||||
isCharging: value?.isCharging ?? false,
|
||||
time: (value?.timeToEmpty == 0 && value?.timeToCharge != 0 ? value?.timeToCharge : value?.timeToEmpty) ?? 0
|
||||
)
|
||||
self.checkNotification(value: value)
|
||||
self.popupView.usageCallback(value)
|
||||
|
||||
self.widgets.filter{ $0.isActive }.forEach { (w: Widget) in
|
||||
switch w.item {
|
||||
case let widget as Mini: widget.setValue(abs(value.level))
|
||||
case let widget as BarChart: widget.setValue([value.level])
|
||||
case let widget as BatterykWidget:
|
||||
widget.setValue(
|
||||
percentage: value.level ,
|
||||
ACStatus: value.powerSource != "Battery Power",
|
||||
isCharging: value.isCharging ,
|
||||
time: value.timeToEmpty == 0 && value.timeToCharge != 0 ? value.timeToCharge : value.timeToEmpty
|
||||
)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ internal class Popup: NSView, Popup_p {
|
||||
self.dashboardBatteryView?.setValue(abs(value.level))
|
||||
|
||||
self.levelField?.stringValue = "\(Int(abs(value.level) * 100)) %"
|
||||
self.sourceField?.stringValue = "\(LocalizedString(value.powerSource))"
|
||||
self.sourceField?.stringValue = LocalizedString(value.powerSource)
|
||||
self.timeField?.stringValue = ""
|
||||
|
||||
if value.powerSource == "Battery Power" {
|
||||
|
||||
@@ -51,11 +51,11 @@ internal class Settings: NSView, Settings_v {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func load(widget: widget_t) {
|
||||
public func load(widgets: [widget_t]) {
|
||||
self.subviews.forEach{ $0.removeFromSuperview() }
|
||||
|
||||
let rowHeight: CGFloat = 30
|
||||
let num: CGFloat = widget == .battery ? 3 : 2
|
||||
let num: CGFloat = widgets.filter{ $0 == .battery }.isEmpty ? 2 : 3
|
||||
let height: CGFloat = ((rowHeight + Constants.Settings.margin) * num) + Constants.Settings.margin
|
||||
|
||||
let levels: [String] = self.levelsList.map { (v: String) -> String in
|
||||
@@ -91,7 +91,7 @@ internal class Settings: NSView, Settings_v {
|
||||
selected: "\(self.numberOfProcesses)"
|
||||
))
|
||||
|
||||
if widget == .battery {
|
||||
if !widgets.filter({ $0 == .battery }).isEmpty {
|
||||
self.addSubview(SelectRow(
|
||||
frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
|
||||
@@ -78,9 +78,6 @@ public class CPU: Module {
|
||||
self.loadReader?.setInterval(value)
|
||||
}
|
||||
|
||||
self.loadReader?.readyCallback = { [unowned self] in
|
||||
self.readyHandler()
|
||||
}
|
||||
self.loadReader?.callbackHandler = { [unowned self] value in
|
||||
self.loadCallback(value)
|
||||
}
|
||||
@@ -116,27 +113,25 @@ public class CPU: Module {
|
||||
}
|
||||
}
|
||||
|
||||
private func loadCallback(_ value: CPU_Load?) {
|
||||
guard value != nil else {
|
||||
private func loadCallback(_ raw: CPU_Load?) {
|
||||
guard let value = raw else {
|
||||
return
|
||||
}
|
||||
|
||||
self.popupView.loadCallback(value!)
|
||||
self.popupView.loadCallback(value)
|
||||
|
||||
if let widget = self.widget as? Mini {
|
||||
widget.setValue(value!.totalUsage)
|
||||
}
|
||||
if let widget = self.widget as? LineChart {
|
||||
widget.setValue(value!.totalUsage)
|
||||
}
|
||||
if let widget = self.widget as? BarChart {
|
||||
widget.setValue(self.usagePerCoreState ? value!.usagePerCore : [value!.totalUsage])
|
||||
}
|
||||
if let widget = self.widget as? PieChart {
|
||||
widget.setValue([
|
||||
circle_segment(value: value!.systemLoad, color: NSColor.systemRed),
|
||||
circle_segment(value: value!.userLoad, color: NSColor.systemBlue)
|
||||
])
|
||||
self.widgets.filter{ $0.isActive }.forEach { (w: Widget) in
|
||||
switch w.item {
|
||||
case let widget as Mini: widget.setValue(value.totalUsage)
|
||||
case let widget as LineChart: widget.setValue(value.totalUsage)
|
||||
case let widget as BarChart: widget.setValue(self.usagePerCoreState ? value.usagePerCore : [value.totalUsage])
|
||||
case let widget as PieChart:
|
||||
widget.setValue([
|
||||
circle_segment(value: value.systemLoad, color: NSColor.systemRed),
|
||||
circle_segment(value: value.userLoad, color: NSColor.systemBlue)
|
||||
])
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,11 +56,11 @@ internal class Settings: NSView, Settings_v {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func load(widget: widget_t) {
|
||||
public func load(widgets: [widget_t]) {
|
||||
self.subviews.forEach{ $0.removeFromSuperview() }
|
||||
|
||||
let rowHeight: CGFloat = 30
|
||||
let num: CGFloat = widget == .barChart ? self.hasHyperthreadingCores ? 3 : 2 : 1
|
||||
let num: CGFloat = !widgets.filter{ $0 == .barChart }.isEmpty ? self.hasHyperthreadingCores ? 3 : 2 : 1
|
||||
|
||||
self.addSubview(SelectTitleRow(
|
||||
frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin + (rowHeight + Constants.Settings.margin) * num, width: self.frame.width - (Constants.Settings.margin*2), height: rowHeight),
|
||||
@@ -70,7 +70,7 @@ internal class Settings: NSView, Settings_v {
|
||||
selected: "\(self.updateIntervalValue) sec"
|
||||
))
|
||||
|
||||
if widget == .barChart {
|
||||
if !widgets.filter({ $0 == .barChart }).isEmpty {
|
||||
self.addSubview(ToggleTitleRow(
|
||||
frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin + (rowHeight + Constants.Settings.margin) * (num-1), width: self.frame.width - (Constants.Settings.margin*2), height: rowHeight),
|
||||
title: LocalizedString("Show usage per core"),
|
||||
|
||||
@@ -105,9 +105,6 @@ public class Disk: Module {
|
||||
self.capacityReader?.store = store
|
||||
self.selectedDisk = store.pointee.string(key: "\(self.config.name)_disk", defaultValue: self.selectedDisk)
|
||||
|
||||
self.capacityReader?.readyCallback = { [unowned self] in
|
||||
self.readyHandler()
|
||||
}
|
||||
self.capacityReader?.callbackHandler = { [unowned self] value in
|
||||
self.capacityCallback(value)
|
||||
}
|
||||
@@ -156,17 +153,14 @@ public class Disk: Module {
|
||||
}
|
||||
let percentage = Double(usedSpace) / Double(total)
|
||||
|
||||
if let widget = self.widget as? Mini {
|
||||
widget.setValue(percentage)
|
||||
}
|
||||
if let widget = self.widget as? BarChart {
|
||||
widget.setValue([percentage])
|
||||
}
|
||||
if let widget = self.widget as? MemoryWidget {
|
||||
widget.setValue((DiskSize(free).getReadableMemory(), DiskSize(usedSpace).getReadableMemory()))
|
||||
}
|
||||
if let widget = self.widget as? SpeedWidget {
|
||||
widget.setValue(upload: d.stats?.write ?? 0, download: d.stats?.read ?? 0)
|
||||
self.widgets.filter{ $0.isActive }.forEach { (w: Widget) in
|
||||
switch w.item {
|
||||
case let widget as Mini: widget.setValue(percentage)
|
||||
case let widget as BarChart: widget.setValue([percentage])
|
||||
case let widget as MemoryWidget: widget.setValue((DiskSize(free).getReadableMemory(), DiskSize(usedSpace).getReadableMemory()))
|
||||
case let widget as SpeedWidget: widget.setValue(upload: d.stats?.write ?? 0, download: d.stats?.read ?? 0)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,22 +49,20 @@ internal class Settings: NSView, Settings_v {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func load(widget: widget_t) {
|
||||
public func load(widgets: [widget_t]) {
|
||||
self.subviews.forEach{ $0.removeFromSuperview() }
|
||||
|
||||
let rowHeight: CGFloat = 30
|
||||
let num: CGFloat = widget != .speed ? 3 : 2
|
||||
let num: CGFloat = 3
|
||||
|
||||
if widget != .speed {
|
||||
self.intervalSelectView = SelectTitleRow(
|
||||
frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin + (rowHeight + Constants.Settings.margin) * 2, width: self.frame.width - (Constants.Settings.margin*2), height: rowHeight),
|
||||
title: LocalizedString("Update interval"),
|
||||
action: #selector(changeUpdateInterval),
|
||||
items: ReaderUpdateIntervals.map{ "\($0) sec" },
|
||||
selected: "\(self.updateIntervalValue) sec"
|
||||
)
|
||||
self.intervalSelectView = SelectTitleRow(
|
||||
frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin + (rowHeight + Constants.Settings.margin) * 2, width: self.frame.width - (Constants.Settings.margin*2), height: rowHeight),
|
||||
title: LocalizedString("Update interval"),
|
||||
action: #selector(changeUpdateInterval),
|
||||
items: ReaderUpdateIntervals.map{ "\($0) sec" },
|
||||
selected: "\(self.updateIntervalValue) sec"
|
||||
)
|
||||
self.addSubview(self.intervalSelectView!)
|
||||
}
|
||||
|
||||
self.addDiskSelector()
|
||||
|
||||
|
||||
@@ -65,9 +65,6 @@ public class Fans: Module {
|
||||
self.fansReader.setInterval(value)
|
||||
}
|
||||
|
||||
self.fansReader.readyCallback = { [unowned self] in
|
||||
self.readyHandler()
|
||||
}
|
||||
self.fansReader.callbackHandler = { [unowned self] value in
|
||||
self.usageCallback(value)
|
||||
}
|
||||
@@ -85,24 +82,27 @@ public class Fans: Module {
|
||||
}
|
||||
}
|
||||
|
||||
private func usageCallback(_ value: [Fan]?) {
|
||||
if value == nil {
|
||||
private func usageCallback(_ raw: [Fan]?) {
|
||||
guard let value = raw else {
|
||||
return
|
||||
}
|
||||
|
||||
self.popupView.usageCallback(value!)
|
||||
self.popupView.usageCallback(value)
|
||||
|
||||
let label: Bool = store.pointee.bool(key: "Fans_label", defaultValue: false)
|
||||
var list: [KeyValue_t] = []
|
||||
value!.forEach { (f: Fan) in
|
||||
value.forEach { (f: Fan) in
|
||||
if f.state {
|
||||
let str = label ? "\(f.name.prefix(1).uppercased()): \(f.formattedValue)" : f.formattedValue
|
||||
list.append(KeyValue_t(key: "Fan#\(f.id)", value: str))
|
||||
}
|
||||
}
|
||||
|
||||
if let widget = self.widget as? SensorsWidget {
|
||||
widget.setValues(list)
|
||||
self.widgets.filter{ $0.isActive }.forEach { (w: Widget) in
|
||||
switch w.item {
|
||||
case let widget as SensorsWidget: widget.setValues(list)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ internal class Settings: NSView, Settings_v {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func load(widget: widget_t) {
|
||||
func load(widgets: [widget_t]) {
|
||||
guard !self.list.pointee.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -93,9 +93,6 @@ public class GPU: Module {
|
||||
self.infoReader?.smc = smc
|
||||
self.selectedGPU = store.pointee.string(key: "\(self.config.name)_gpu", defaultValue: self.selectedGPU)
|
||||
|
||||
self.infoReader?.readyCallback = { [unowned self] in
|
||||
self.readyHandler()
|
||||
}
|
||||
self.infoReader?.callbackHandler = { [unowned self] value in
|
||||
self.infoCallback(value)
|
||||
}
|
||||
@@ -135,15 +132,15 @@ public class GPU: Module {
|
||||
return
|
||||
}
|
||||
|
||||
if let widget = self.widget as? Mini {
|
||||
widget.setValue(utilization)
|
||||
widget.setTitle(self.showType ? "\(selectedGPU.type)GPU" : nil)
|
||||
}
|
||||
if let widget = self.widget as? LineChart {
|
||||
widget.setValue(utilization)
|
||||
}
|
||||
if let widget = self.widget as? BarChart {
|
||||
widget.setValue([utilization])
|
||||
self.widgets.filter{ $0.isActive }.forEach { (w: Widget) in
|
||||
switch w.item {
|
||||
case let widget as Mini:
|
||||
widget.setValue(utilization)
|
||||
widget.setTitle(self.showType ? "\(selectedGPU.type)GPU" : nil)
|
||||
case let widget as LineChart: widget.setValue(utilization)
|
||||
case let widget as BarChart: widget.setValue([utilization])
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,11 +50,11 @@ internal class Settings: NSView, Settings_v {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func load(widget: widget_t) {
|
||||
public func load(widgets: [widget_t]) {
|
||||
self.subviews.forEach{ $0.removeFromSuperview() }
|
||||
|
||||
let rowHeight: CGFloat = 30
|
||||
let num: CGFloat = widget == .mini ? 3 : 2
|
||||
let num: CGFloat = widgets.filter{ $0 == .mini }.isEmpty ? 2 : 3
|
||||
|
||||
self.addSubview(SelectTitleRow(
|
||||
frame: NSRect(
|
||||
@@ -69,7 +69,7 @@ internal class Settings: NSView, Settings_v {
|
||||
selected: "\(self.updateIntervalValue) sec"
|
||||
))
|
||||
|
||||
if widget == .mini {
|
||||
if !widgets.filter({ $0 == .mini }).isEmpty {
|
||||
self.addSubview(ToggleTitleRow(
|
||||
frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
|
||||
@@ -95,9 +95,6 @@ public class Network: Module {
|
||||
}
|
||||
}
|
||||
|
||||
self.usageReader?.readyCallback = { [unowned self] in
|
||||
self.readyHandler()
|
||||
}
|
||||
self.usageReader?.callbackHandler = { [unowned self] value in
|
||||
self.usageCallback(value)
|
||||
}
|
||||
@@ -131,16 +128,19 @@ public class Network: Module {
|
||||
return list.count > 0
|
||||
}
|
||||
|
||||
private func usageCallback(_ value: Network_Usage?) {
|
||||
guard let value = value else {
|
||||
private func usageCallback(_ raw: Network_Usage?) {
|
||||
guard let value = raw else {
|
||||
return
|
||||
}
|
||||
|
||||
self.popupView.usageCallback(value)
|
||||
if let widget = self.widget as? SpeedWidget {
|
||||
widget.setValue(upload: value.bandwidth.upload, download: value.bandwidth.download)
|
||||
} else if let widget = self.widget as? NetworkChart {
|
||||
widget.setValue(upload: Double(value.bandwidth.upload), download: Double(value.bandwidth.download))
|
||||
|
||||
self.widgets.filter{ $0.isActive }.forEach { (w: Widget) in
|
||||
switch w.item {
|
||||
case let widget as SpeedWidget: widget.setValue(upload: value.bandwidth.upload, download: value.bandwidth.download)
|
||||
case let widget as NetworkChart: widget.setValue(upload: Double(value.bandwidth.upload), download: Double(value.bandwidth.download))
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ internal class Settings: NSView, Settings_v {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func load(widget: widget_t) {
|
||||
public func load(widgets: [widget_t]) {
|
||||
self.subviews.forEach{ $0.removeFromSuperview() }
|
||||
|
||||
let rowHeight: CGFloat = 30
|
||||
|
||||
@@ -81,9 +81,6 @@ public class RAM: Module {
|
||||
}
|
||||
}
|
||||
|
||||
self.usageReader?.readyCallback = { [unowned self] in
|
||||
self.readyHandler()
|
||||
}
|
||||
self.usageReader?.callbackHandler = { [unowned self] value in
|
||||
self.loadCallback(value)
|
||||
}
|
||||
@@ -108,30 +105,31 @@ public class RAM: Module {
|
||||
}
|
||||
|
||||
self.popupView.loadCallback(value)
|
||||
if let widget = self.widget as? Mini {
|
||||
widget.setValue(value.usage)
|
||||
widget.setPressure(value.pressureLevel)
|
||||
}
|
||||
if let widget = self.widget as? LineChart {
|
||||
widget.setValue(value.usage)
|
||||
widget.setPressure(value.pressureLevel)
|
||||
}
|
||||
if let widget = self.widget as? BarChart {
|
||||
widget.setValue([value.usage])
|
||||
widget.setPressure(value.pressureLevel)
|
||||
}
|
||||
if let widget = self.widget as? PieChart {
|
||||
let total: Double = value.total
|
||||
widget.setValue([
|
||||
circle_segment(value: value.app/total, color: NSColor.systemBlue),
|
||||
circle_segment(value: value.wired/total, color: NSColor.systemOrange),
|
||||
circle_segment(value: value.compressed/total, color: NSColor.systemPink)
|
||||
])
|
||||
}
|
||||
if let widget = self.widget as? MemoryWidget {
|
||||
let free = Units(bytes: Int64(value.free)).getReadableMemory()
|
||||
let used = Units(bytes: Int64(value.used)).getReadableMemory()
|
||||
widget.setValue((free, used))
|
||||
|
||||
self.widgets.filter{ $0.isActive }.forEach { (w: Widget) in
|
||||
switch w.item {
|
||||
case let widget as Mini:
|
||||
widget.setValue(value.usage)
|
||||
widget.setPressure(value.pressureLevel)
|
||||
case let widget as LineChart:
|
||||
widget.setValue(value.usage)
|
||||
widget.setPressure(value.pressureLevel)
|
||||
case let widget as BarChart:
|
||||
widget.setValue([value.usage])
|
||||
widget.setPressure(value.pressureLevel)
|
||||
case let widget as PieChart:
|
||||
let total: Double = value.total == 0 ? 1 : value.total
|
||||
widget.setValue([
|
||||
circle_segment(value: value.app/total, color: NSColor.systemBlue),
|
||||
circle_segment(value: value.wired/total, color: NSColor.systemOrange),
|
||||
circle_segment(value: value.compressed/total, color: NSColor.systemPink)
|
||||
])
|
||||
case let widget as MemoryWidget:
|
||||
let free = Units(bytes: Int64(value.free)).getReadableMemory()
|
||||
let used = Units(bytes: Int64(value.used)).getReadableMemory()
|
||||
widget.setValue((free, used))
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ internal class Settings: NSView, Settings_v {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func load(widget: widget_t) {
|
||||
public func load(widgets: [widget_t]) {
|
||||
self.subviews.forEach{ $0.removeFromSuperview() }
|
||||
|
||||
let rowHeight: CGFloat = 30
|
||||
|
||||
@@ -40,9 +40,6 @@ public class Sensors: Module {
|
||||
self.sensorsReader.setInterval(value)
|
||||
}
|
||||
|
||||
self.sensorsReader.readyCallback = { [unowned self] in
|
||||
self.readyHandler()
|
||||
}
|
||||
self.sensorsReader.callbackHandler = { [unowned self] value in
|
||||
self.usageCallback(value)
|
||||
}
|
||||
@@ -60,21 +57,25 @@ public class Sensors: Module {
|
||||
}
|
||||
}
|
||||
|
||||
private func usageCallback(_ value: [Sensor_t]?) {
|
||||
if value == nil {
|
||||
private func usageCallback(_ raw: [Sensor_t]?) {
|
||||
guard let value = raw else {
|
||||
return
|
||||
}
|
||||
|
||||
var list: [KeyValue_t] = []
|
||||
value!.forEach { (s: Sensor_t) in
|
||||
value.forEach { (s: Sensor_t) in
|
||||
if s.state {
|
||||
list.append(KeyValue_t(key: s.key, value: s.formattedMiniValue))
|
||||
}
|
||||
}
|
||||
|
||||
self.popupView.usageCallback(value!)
|
||||
if let widget = self.widget as? SensorsWidget {
|
||||
widget.setValues(list)
|
||||
self.popupView.usageCallback(value)
|
||||
|
||||
self.widgets.filter{ $0.isActive }.forEach { (w: Widget) in
|
||||
switch w.item {
|
||||
case let widget as SensorsWidget: widget.setValues(list)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ internal class Settings: NSView, Settings_v {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func load(widget: widget_t) {
|
||||
public func load(widgets: [widget_t]) {
|
||||
guard !self.list.pointee.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public class NetworkChartView: NSView {
|
||||
context.saveGState()
|
||||
|
||||
var underLinePath = uploadlinePath.copy() as! NSBezierPath
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(points.count - 1), y: zero))
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(points.count), y: zero))
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(0), y: zero))
|
||||
underLinePath.close()
|
||||
underLinePath.addClip()
|
||||
@@ -188,7 +188,7 @@ public class NetworkChartView: NSView {
|
||||
context.saveGState()
|
||||
|
||||
underLinePath = downloadlinePath.copy() as! NSBezierPath
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(points.count - 1), y: zero))
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(points.count), y: zero))
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(0), y: zero))
|
||||
underLinePath.close()
|
||||
underLinePath.addClip()
|
||||
|
||||
@@ -387,6 +387,8 @@ public extension NSView {
|
||||
public extension Notification.Name {
|
||||
static let toggleSettings = Notification.Name("toggleSettings")
|
||||
static let toggleModule = Notification.Name("toggleModule")
|
||||
static let togglePopup = Notification.Name("togglePopup")
|
||||
static let toggleWidget = Notification.Name("toggleWidget")
|
||||
static let openModuleSettings = Notification.Name("openModuleSettings")
|
||||
static let settingsAppear = Notification.Name("settingsAppear")
|
||||
static let switchWidget = Notification.Name("switchWidget")
|
||||
@@ -398,12 +400,12 @@ public extension Notification.Name {
|
||||
public class NSButtonWithPadding: NSButton {
|
||||
public var horizontalPadding: CGFloat = 0
|
||||
public var verticalPadding: CGFloat = 0
|
||||
|
||||
|
||||
public override var intrinsicContentSize: NSSize {
|
||||
var size = super.intrinsicContentSize
|
||||
size.width += self.horizontalPadding
|
||||
size.height += self.verticalPadding
|
||||
return size;
|
||||
return size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,3 +509,52 @@ public extension CATransaction {
|
||||
CATransaction.commit()
|
||||
}
|
||||
}
|
||||
|
||||
public final class FlippedClipView: NSClipView {
|
||||
public override var isFlipped: Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public final class ScrollableStackView: NSView {
|
||||
public let stackView: NSStackView = NSStackView()
|
||||
public let clipView: FlippedClipView = FlippedClipView()
|
||||
private let scrollView: NSScrollView = NSScrollView()
|
||||
|
||||
public override init(frame: NSRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
||||
scrollView.borderType = .noBorder
|
||||
scrollView.hasVerticalScroller = true
|
||||
scrollView.hasHorizontalScroller = false
|
||||
scrollView.autohidesScrollers = true
|
||||
scrollView.horizontalScrollElasticity = .none
|
||||
scrollView.drawsBackground = false
|
||||
self.addSubview(self.scrollView)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
scrollView.leftAnchor.constraint(equalTo: self.leftAnchor),
|
||||
scrollView.rightAnchor.constraint(equalTo: self.rightAnchor),
|
||||
scrollView.topAnchor.constraint(equalTo: self.topAnchor),
|
||||
scrollView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
|
||||
])
|
||||
|
||||
clipView.drawsBackground = false
|
||||
scrollView.contentView = clipView
|
||||
|
||||
stackView.orientation = .vertical
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
scrollView.documentView = stackView
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
stackView.leftAnchor.constraint(equalTo: clipView.leftAnchor),
|
||||
stackView.rightAnchor.constraint(equalTo: clipView.rightAnchor),
|
||||
stackView.topAnchor.constraint(equalTo: clipView.topAnchor),
|
||||
])
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user