From 8dbafa40ac3592f876a54e80a208a078aa9168ec Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Fri, 10 Jul 2020 22:56:47 +0200 Subject: [PATCH] - add option to set up update interval for CPU module - add setInterval() to reader protocol - update reader start process (run initStoreValues() before start()) - add option to select update interval for RAM module - add option to select update interval for Disk module - small refactoring in cpu and ram settings - add option to select update interval for Sensors module --- ModuleKit/module.swift | 24 ++++++----- ModuleKit/reader.swift | 40 ++++++++++++++---- Modules/Battery/main.swift | 2 +- Modules/CPU/main.swift | 3 ++ Modules/CPU/readers.swift | 2 - Modules/CPU/settings.swift | 50 ++++++++++++++++------- Modules/Disk/main.swift | 9 +++-- Modules/Disk/readers.swift | 4 -- Modules/Disk/settings.swift | 38 +++++++++++++++-- Modules/Memory/main.swift | 11 ++++- Modules/Memory/settings.swift | 72 +++++++++++++++++++++++++++++++++ Modules/Net/main.swift | 4 +- Modules/Sensors/main.swift | 7 +++- Modules/Sensors/settings.swift | 35 +++++++++++++++- Stats.xcodeproj/project.pbxproj | 4 ++ 15 files changed, 252 insertions(+), 53 deletions(-) create mode 100644 Modules/Memory/settings.swift diff --git a/ModuleKit/module.swift b/ModuleKit/module.swift index 002da0f4..dc7c0d27 100644 --- a/ModuleKit/module.swift +++ b/ModuleKit/module.swift @@ -72,12 +72,12 @@ open class Module: Module_p { private var popup: NSWindow = NSWindow() private let log: OSLog - private var store: UnsafePointer? = nil + private var store: UnsafePointer 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) + 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 {} @@ -85,14 +85,14 @@ open class Module: Module_p { private var ready: Bool = false private var widgetLoaded: Bool = false - public init(store: UnsafePointer?, popup: NSView?, settings: Settings_v?) { + public init(store: UnsafePointer, popup: NSView?, settings: Settings_v?) { self.config = module_c(in: Bundle(for: type(of: self)).path(forResource: "config", ofType: "plist")!) self.log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: self.config.name) self.store = store self.settingsView = settings self.available = self.isAvailable() - self.enabled = self.store?.pointee.bool(key: "\(self.config.name)_state", defaultValue: self.config.defaultState) ?? false + self.enabled = self.store.pointee.bool(key: "\(self.config.name)_state", defaultValue: self.config.defaultState) self.menuBarItem.isVisible = self.enabled self.menuBarItem.autosaveName = self.config.name @@ -126,7 +126,10 @@ open class Module: Module_p { return } - self.readers.forEach{ $0.start() } + self.readers.forEach { (reader: Reader_p) in + reader.initStoreValues(title: self.config.name, store: self.store) + reader.start() + } } // disable module @@ -154,8 +157,11 @@ open class Module: Module_p { guard self.available else { return } self.enabled = true - self.store?.pointee.set(key: "\(self.config.name)_state", value: true) - self.readers.forEach{ $0.start() } + self.store.pointee.set(key: "\(self.config.name)_state", value: true) + self.readers.forEach { (reader: Reader_p) in + reader.initStoreValues(title: self.config.name, store: self.store) + reader.start() + } self.menuBarItem.isVisible = true if self.menuBarItem.length < 0 { self.loadWidget() @@ -168,7 +174,7 @@ open class Module: Module_p { guard self.available else { return } self.enabled = false - self.store?.pointee.set(key: "\(self.config.name)_state", value: false) + self.store.pointee.set(key: "\(self.config.name)_state", value: false) self.readers.forEach{ $0.pause() } self.menuBarItem.isVisible = false self.popup.setIsVisible(false) @@ -302,7 +308,7 @@ open class Module: Module_p { 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.store.pointee.set(key: "\(self.config.name)_widget", value: widgetType.rawValue) self.setWidget() os_log(.debug, log: log, "Widget is changed to: %s", "\(widgetName)") } diff --git a/ModuleKit/reader.swift b/ModuleKit/reader.swift index 9207a4e4..41a63fca 100644 --- a/ModuleKit/reader.swift +++ b/ModuleKit/reader.swift @@ -12,6 +12,7 @@ import Cocoa import Repeat import os.log +import StatsKit public protocol value_t { var widget_value: Double { get } @@ -30,6 +31,9 @@ public protocol Reader_p { func start() -> Void func pause() -> Void func stop() -> Void + + func initStoreValues(title: String, store: UnsafePointer) -> Void + func setInterval(_ value: Double) -> Void } public protocol ReaderInternal_p { @@ -42,7 +46,7 @@ public protocol ReaderInternal_p { open class Reader: ReaderInternal_p { public let log: OSLog public var value: T? - public var interval: Int = 1000 + public var interval: Double? = nil public var optional: Bool = false public var readyCallback: () -> Void = {} @@ -59,13 +63,20 @@ open class Reader: ReaderInternal_p { self.setup() - self.repeatTask = Repeater.init(interval: .milliseconds(self.interval), observer: { _ in - self.read() - }) - os_log(.debug, log: self.log, "Successfully initialize reader") } + public func initStoreValues(title: String, store: UnsafePointer) { + guard self.interval == nil else { + return + } + + let updateIntervalString = store.pointee.string(key: "\(title)_updateInterval", defaultValue: "1") + if let updateInterval = Double(updateIntervalString) { + self.interval = updateInterval + } + } + public func callback(_ value: T?) { if !self.optional && !self.ready { if self.value == nil && value != nil { @@ -103,16 +114,29 @@ open class Reader: ReaderInternal_p { open func terminate() {} open func start() { + if let interval = self.interval, self.repeatTask == nil { + os_log(.debug, log: self.log, "Set up update interval: %.0f sec", interval) + + self.repeatTask = Repeater.init(interval: .seconds(interval), observer: { _ in + self.read() + }) + } + self.read() - self.repeatTask!.start() + self.repeatTask?.start() } open func pause() { - self.repeatTask!.pause() + self.repeatTask?.pause() } open func stop() { - self.repeatTask!.removeAllObservers(thenStop: true) + self.repeatTask?.removeAllObservers(thenStop: true) + } + + public func setInterval(_ value: Double) { + os_log(.debug, log: self.log, "Set update interval: %.0f sec", value) + self.repeatTask?.reset(.seconds(value), restart: true) } } diff --git a/Modules/Battery/main.swift b/Modules/Battery/main.swift index 32235bb0..2994c840 100644 --- a/Modules/Battery/main.swift +++ b/Modules/Battery/main.swift @@ -43,7 +43,7 @@ public class Battery: Module { private var usageReader: UsageReader? = nil private let popupView: Popup = Popup() - public init(_ store: UnsafePointer?) { + public init(_ store: UnsafePointer) { super.init( store: store, popup: self.popupView, diff --git a/Modules/CPU/main.swift b/Modules/CPU/main.swift index d0e13675..e82912e2 100644 --- a/Modules/CPU/main.swift +++ b/Modules/CPU/main.swift @@ -55,6 +55,9 @@ public class CPU: Module { self.settingsView.callback = { [unowned self] in self.loadReader?.read() } + self.settingsView.setInterval = { [unowned self] value in + self.loadReader?.setInterval(value) + } self.loadReader?.readyCallback = { [unowned self] in self.readyHandler() diff --git a/Modules/CPU/readers.swift b/Modules/CPU/readers.swift index 54ddb0d2..35cf5a25 100644 --- a/Modules/CPU/readers.swift +++ b/Modules/CPU/readers.swift @@ -29,8 +29,6 @@ internal class LoadReader: Reader { private var usagePerCore: [Double] = [] public override func setup() { - self.interval = 1500 - [CTL_HW, HW_NCPU].withUnsafeBufferPointer() { mib in var sizeOfNumCPUs: size_t = MemoryLayout.size let status = sysctl(processor_info_array_t(mutating: mib.baseAddress), 2, &numCPUs, &sizeOfNumCPUs, nil, 0) diff --git a/Modules/CPU/settings.swift b/Modules/CPU/settings.swift index dc68d149..df09cf3a 100644 --- a/Modules/CPU/settings.swift +++ b/Modules/CPU/settings.swift @@ -15,22 +15,30 @@ import ModuleKit internal class Settings: NSView, Settings_v { private var hyperthreadState: Bool = false + private var updateIntervalValue: String = "1" + private let listOfUpdateIntervals: [String] = ["1", "2", "3", "5", "10", "15", "30"] private let title: String - private let store: UnsafePointer? + private let store: UnsafePointer public var callback: (() -> Void) = {} + public var setInterval: ((_ value: Double) -> Void) = {_ in } - public init(_ title: String, store: UnsafePointer?) { + public init(_ title: String, store: UnsafePointer) { self.title = title self.store = store - super.init(frame: CGRect(x: Constants.Settings.margin, y: Constants.Settings.margin, width: Constants.Settings.width - (Constants.Settings.margin*2), height: 0)) + self.hyperthreadState = store.pointee.bool(key: "\(self.title)_hyperhreading", defaultValue: self.hyperthreadState) + self.updateIntervalValue = store.pointee.string(key: "\(self.title)_updateInterval", defaultValue: self.updateIntervalValue) + + super.init(frame: CGRect( + x: Constants.Settings.margin, + y: Constants.Settings.margin, + width: Constants.Settings.width - (Constants.Settings.margin*2), + height: 0 + )) + self.wantsLayer = true self.canDrawConcurrently = true - - if self.store != nil { - self.hyperthreadState = store!.pointee.bool(key: "\(self.title)_hyperhreading", defaultValue: self.hyperthreadState) - } } required init?(coder: NSCoder) { @@ -40,8 +48,16 @@ internal class Settings: NSView, Settings_v { public func load(widget: widget_t) { self.subviews.forEach{ $0.removeFromSuperview() } - let rowHeight: CGFloat = 29 - var height: CGFloat = 0 + let rowHeight: CGFloat = 30 + let num: CGFloat = widget == .barChart ? 1 : 0 + + 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), + title: "Update interval", + action: #selector(changeUpdateInterval), + items: self.listOfUpdateIntervals.map{ "\($0) sec" }, + selected: "\(self.updateIntervalValue) sec" + )) if widget == .barChart { self.addSubview(ToggleTitleRow( @@ -50,13 +66,19 @@ internal class Settings: NSView, Settings_v { action: #selector(toggleMultithreading), state: self.hyperthreadState )) - height += rowHeight } - if height != 0 { - height += (Constants.Settings.margin*2) + self.setFrameSize(NSSize(width: self.frame.width, height: (rowHeight*(num+1)) + (Constants.Settings.margin*(2+num)))) + } + + @objc private func changeUpdateInterval(_ sender: NSMenuItem) { + let newUpdateInterval = sender.title.replacingOccurrences(of: " sec", with: "") + self.updateIntervalValue = newUpdateInterval + store.pointee.set(key: "\(self.title)_updateInterval", value: self.updateIntervalValue) + + if let value = Double(self.updateIntervalValue) { + self.setInterval(value) } - self.setFrameSize(NSSize(width: self.frame.width, height: height)) } @objc func toggleMultithreading(_ sender: NSControl) { @@ -68,7 +90,7 @@ internal class Settings: NSView, Settings_v { } self.hyperthreadState = state! == .on ? true : false - self.store?.pointee.set(key: "\(self.title)_hyperhreading", value: self.hyperthreadState) + self.store.pointee.set(key: "\(self.title)_hyperhreading", value: self.hyperthreadState) self.callback() } } diff --git a/Modules/Disk/main.swift b/Modules/Disk/main.swift index f1fe790e..61b9803f 100644 --- a/Modules/Disk/main.swift +++ b/Modules/Disk/main.swift @@ -69,8 +69,8 @@ public class Disk: Module { private var settingsView: Settings private var selectedDisk: String = "" - public init(_ store: UnsafePointer?) { - self.settingsView = Settings("Disk", store: store!) + public init(_ store: UnsafePointer) { + self.settingsView = Settings("Disk", store: store) super.init( store: store, @@ -81,7 +81,7 @@ public class Disk: Module { self.capacityReader = CapacityReader() self.capacityReader?.store = store - self.selectedDisk = store!.pointee.string(key: "\(self.config.name)_disk", defaultValue: self.selectedDisk) + self.selectedDisk = store.pointee.string(key: "\(self.config.name)_disk", defaultValue: self.selectedDisk) self.capacityReader?.readyCallback = { [unowned self] in self.readyHandler() @@ -97,6 +97,9 @@ public class Disk: Module { self.settingsView.callback = { [unowned self] in self.capacityReader?.read() } + self.settingsView.setInterval = { [unowned self] value in + self.capacityReader?.setInterval(value) + } if let reader = self.capacityReader { self.addReader(reader) diff --git a/Modules/Disk/readers.swift b/Modules/Disk/readers.swift index abb4da0d..4203aeac 100644 --- a/Modules/Disk/readers.swift +++ b/Modules/Disk/readers.swift @@ -17,10 +17,6 @@ internal class CapacityReader: Reader { private var disks: DiskList = DiskList() public var store: UnsafePointer? = nil - public override func setup() { - self.interval = 10000 - } - public override func read() { let keys: [URLResourceKey] = [.volumeNameKey] let removableState = store?.pointee.bool(key: "Disk_removable", defaultValue: false) ?? false diff --git a/Modules/Disk/settings.swift b/Modules/Disk/settings.swift index e221972c..d8cb5d57 100644 --- a/Modules/Disk/settings.swift +++ b/Modules/Disk/settings.swift @@ -14,22 +14,33 @@ import StatsKit import ModuleKit internal class Settings: NSView, Settings_v { + private var removableState: Bool = false + private var updateIntervalValue: String = "10" + private let listOfUpdateIntervals: [String] = ["1", "2", "3", "5", "10", "15", "30"] + public var selectedDiskHandler: (String) -> Void = {_ in } public var callback: (() -> Void) = {} + public var setInterval: ((_ value: Double) -> Void) = {_ in } private let title: String private let store: UnsafePointer private var selectedDisk: String private var button: NSPopUpButton? - private var removableState: Bool = false - public init(_ title: String, store: UnsafePointer) { self.title = title self.store = store self.selectedDisk = store.pointee.string(key: "\(self.title)_disk", defaultValue: "") self.removableState = store.pointee.bool(key: "\(self.title)_removable", defaultValue: self.removableState) - super.init(frame: CGRect(x: Constants.Settings.margin, y: Constants.Settings.margin, width: Constants.Settings.width - (Constants.Settings.margin*2), height: 0)) + self.updateIntervalValue = store.pointee.string(key: "\(self.title)_updateInterval", defaultValue: self.updateIntervalValue) + + super.init(frame: CGRect( + x: Constants.Settings.margin, + y: Constants.Settings.margin, + width: Constants.Settings.width - (Constants.Settings.margin*2), + height: 0 + )) + self.wantsLayer = true self.canDrawConcurrently = true } @@ -42,6 +53,15 @@ internal class Settings: NSView, Settings_v { self.subviews.forEach{ $0.removeFromSuperview() } let rowHeight: CGFloat = 30 + + self.addSubview(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: "Update interval", + action: #selector(changeUpdateInterval), + items: self.listOfUpdateIntervals.map{ "\($0) sec" }, + selected: "\(self.updateIntervalValue) sec" + )) + self.addDiskSelector() self.addSubview(ToggleTitleRow( @@ -51,7 +71,7 @@ internal class Settings: NSView, Settings_v { state: self.removableState )) - self.setFrameSize(NSSize(width: self.frame.width, height: rowHeight*2 + (Constants.Settings.margin*3))) + self.setFrameSize(NSSize(width: self.frame.width, height: rowHeight*3 + (Constants.Settings.margin*4))) } private func addDiskSelector() { @@ -106,4 +126,14 @@ internal class Settings: NSView, Settings_v { self.store.pointee.set(key: "\(self.title)_removable", value: self.removableState) self.callback() } + + @objc private func changeUpdateInterval(_ sender: NSMenuItem) { + let newUpdateInterval = sender.title.replacingOccurrences(of: " sec", with: "") + self.updateIntervalValue = newUpdateInterval + store.pointee.set(key: "\(self.title)_updateInterval", value: self.updateIntervalValue) + + if let value = Double(self.updateIntervalValue) { + self.setInterval(value) + } + } } diff --git a/Modules/Memory/main.swift b/Modules/Memory/main.swift index 866bad16..662380d9 100644 --- a/Modules/Memory/main.swift +++ b/Modules/Memory/main.swift @@ -36,15 +36,22 @@ public struct RAM_Usage: value_t { public class Memory: Module { private let popupView: Popup = Popup() private var usageReader: UsageReader? = nil + private var settingsView: Settings - public init(_ store: UnsafePointer?) { + public init(_ store: UnsafePointer) { + self.settingsView = Settings("RAM", store: store) + super.init( store: store, popup: self.popupView, - settings: nil + settings: self.settingsView ) guard self.available else { return } + self.settingsView.setInterval = { [unowned self] value in + self.usageReader?.setInterval(value) + } + self.usageReader = UsageReader() self.usageReader?.readyCallback = { [unowned self] in diff --git a/Modules/Memory/settings.swift b/Modules/Memory/settings.swift new file mode 100644 index 00000000..7913831a --- /dev/null +++ b/Modules/Memory/settings.swift @@ -0,0 +1,72 @@ +// +// settings.swift +// Memory +// +// Created by Serhiy Mytrovtsiy on 11/07/2020. +// Using Swift 5.0. +// Running on macOS 10.15. +// +// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved. +// + +import Cocoa +import StatsKit +import ModuleKit + +internal class Settings: NSView, Settings_v { + private var updateIntervalValue: String = "1" + private let listOfUpdateIntervals: [String] = ["1", "2", "3", "5", "10", "15", "30"] + + private let title: String + private let store: UnsafePointer + + public var callback: (() -> Void) = {} + public var setInterval: ((_ value: Double) -> Void) = {_ in } + + public init(_ title: String, store: UnsafePointer) { + self.title = title + self.store = store + self.updateIntervalValue = store.pointee.string(key: "\(self.title)_updateInterval", defaultValue: self.updateIntervalValue) + + super.init(frame: CGRect( + x: Constants.Settings.margin, + y: Constants.Settings.margin, + width: Constants.Settings.width - (Constants.Settings.margin*2), + height: 0 + )) + + self.wantsLayer = true + self.canDrawConcurrently = true + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func load(widget: widget_t) { + self.subviews.forEach{ $0.removeFromSuperview() } + + let rowHeight: CGFloat = 30 + let num: CGFloat = 0 + + 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), + title: "Update interval", + action: #selector(changeUpdateInterval), + items: self.listOfUpdateIntervals.map{ "\($0) sec" }, + selected: "\(self.updateIntervalValue) sec" + )) + + self.setFrameSize(NSSize(width: self.frame.width, height: (rowHeight*(num+1)) + (Constants.Settings.margin*(2+num)))) + } + + @objc private func changeUpdateInterval(_ sender: NSMenuItem) { + let newUpdateInterval = sender.title.replacingOccurrences(of: " sec", with: "") + self.updateIntervalValue = newUpdateInterval + store.pointee.set(key: "\(self.title)_updateInterval", value: self.updateIntervalValue) + + if let value = Double(self.updateIntervalValue) { + self.setInterval(value) + } + } +} diff --git a/Modules/Net/main.swift b/Modules/Net/main.swift index a538fadd..5bd1d4f6 100644 --- a/Modules/Net/main.swift +++ b/Modules/Net/main.swift @@ -62,8 +62,8 @@ public class Network: Module { private let popupView: Popup = Popup() private var settingsView: Settings - public init(_ store: UnsafePointer?) { - self.settingsView = Settings("Network", store: store!) + public init(_ store: UnsafePointer) { + self.settingsView = Settings("Network", store: store) super.init( store: store, diff --git a/Modules/Sensors/main.swift b/Modules/Sensors/main.swift index d270cefa..a9b0a33d 100644 --- a/Modules/Sensors/main.swift +++ b/Modules/Sensors/main.swift @@ -18,9 +18,9 @@ public class Sensors: Module { private let popupView: Popup = Popup() private var settingsView: Settings - public init(_ store: UnsafePointer?, _ smc: UnsafePointer) { + public init(_ store: UnsafePointer, _ smc: UnsafePointer) { self.sensorsReader = SensorsReader(smc) - self.settingsView = Settings("Disk", store: store!, list: &self.sensorsReader.list) + self.settingsView = Settings("Sensors", store: store, list: &self.sensorsReader.list) super.init( store: store, @@ -36,6 +36,9 @@ public class Sensors: Module { self.checkIfNoSensorsEnabled() self.sensorsReader.read() } + self.settingsView.setInterval = { [unowned self] value in + self.sensorsReader.setInterval(value) + } self.sensorsReader.readyCallback = { [unowned self] in self.readyHandler() diff --git a/Modules/Sensors/settings.swift b/Modules/Sensors/settings.swift index d8e722d9..22ed3b41 100644 --- a/Modules/Sensors/settings.swift +++ b/Modules/Sensors/settings.swift @@ -14,19 +14,32 @@ import StatsKit import ModuleKit internal class Settings: NSView, Settings_v { + private var updateIntervalValue: String = "3" + private let listOfUpdateIntervals: [String] = ["1", "2", "3", "5", "10", "15", "30"] + private let title: String private let store: UnsafePointer private var button: NSPopUpButton? private let list: UnsafeMutablePointer<[Sensor_t]> public var callback: (() -> Void) = {} + public var setInterval: ((_ value: Double) -> Void) = {_ in } public init(_ title: String, store: UnsafePointer, list: UnsafeMutablePointer<[Sensor_t]>) { self.title = title self.store = store self.list = list - super.init(frame: CGRect(x: Constants.Settings.margin, y: Constants.Settings.margin, width: Constants.Settings.width - (Constants.Settings.margin*2), height: 0)) + + super.init(frame: CGRect( + x: Constants.Settings.margin, + y: Constants.Settings.margin, + width: Constants.Settings.width - (Constants.Settings.margin*2), + height: 0 + )) + self.wantsLayer = true self.canDrawConcurrently = true + + self.updateIntervalValue = store.pointee.string(key: "\(self.title)_updateInterval", defaultValue: self.updateIntervalValue) } required init?(coder: NSCoder) { @@ -45,10 +58,18 @@ internal class Settings: NSView, Settings_v { } let rowHeight: CGFloat = 30 - let height: CGFloat = ((rowHeight+Constants.Settings.margin) * CGFloat(self.list.pointee.count)) + ((rowHeight+Constants.Settings.margin) * CGFloat(types.count)) + let height: CGFloat = ((rowHeight+Constants.Settings.margin) * CGFloat(self.list.pointee.count) + rowHeight) + ((rowHeight+Constants.Settings.margin) * CGFloat(types.count) + 1) let x: CGFloat = height < 360 ? 0 : Constants.Settings.margin let view: NSView = NSView(frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin, width: self.frame.width - (Constants.Settings.margin*2) - x, height: height)) + self.addSubview(SelectTitleRow( + frame: NSRect(x: Constants.Settings.margin, y: height - rowHeight, width: self.frame.width - (Constants.Settings.margin*2), height: rowHeight), + title: "Update interval", + action: #selector(changeUpdateInterval), + items: self.listOfUpdateIntervals.map{ "\($0) sec" }, + selected: "\(self.updateIntervalValue) sec" + )) + var y: CGFloat = 0 types.sorted{ $0.1 < $1.1 }.forEach { (t: (key: SensorType_t, value: Int)) in let filtered = self.list.pointee.filter{ $0.type == t.key } @@ -101,4 +122,14 @@ internal class Settings: NSView, Settings_v { self.store.pointee.set(key: "sensor_\(id.rawValue)", value: state! == NSControl.StateValue.on) self.callback() } + + @objc private func changeUpdateInterval(_ sender: NSMenuItem) { + let newUpdateInterval = sender.title.replacingOccurrences(of: " sec", with: "") + self.updateIntervalValue = newUpdateInterval + store.pointee.set(key: "\(self.title)_updateInterval", value: self.updateIntervalValue) + + if let value = Double(self.updateIntervalValue) { + self.setInterval(value) + } + } } diff --git a/Stats.xcodeproj/project.pbxproj b/Stats.xcodeproj/project.pbxproj index 9708e3d9..abaa703c 100644 --- a/Stats.xcodeproj/project.pbxproj +++ b/Stats.xcodeproj/project.pbxproj @@ -63,6 +63,7 @@ 9A944D5D24492A8B0058F32A /* popup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A944D5C24492A8B0058F32A /* popup.swift */; }; 9A944D5F24492AA60058F32A /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A944D5E24492AA60058F32A /* Constants.swift */; }; 9A944D6124492B6D0058F32A /* popup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A944D6024492B6D0058F32A /* popup.swift */; }; + 9A953A1424B9D22D0038EF4B /* settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A953A1324B9D22D0038EF4B /* settings.swift */; }; 9A9D728A24471FAE005CF997 /* SMC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9D728924471FAE005CF997 /* SMC.swift */; }; 9A9EA9452476D34500E3B883 /* Update.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9EA9442476D34500E3B883 /* Update.swift */; }; 9AA4A00A2443656D00ECCF07 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9AA4A0092443656D00ECCF07 /* Assets.xcassets */; }; @@ -441,6 +442,7 @@ 9A944D5C24492A8B0058F32A /* popup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = popup.swift; sourceTree = ""; }; 9A944D5E24492AA60058F32A /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; 9A944D6024492B6D0058F32A /* popup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = popup.swift; sourceTree = ""; }; + 9A953A1324B9D22D0038EF4B /* settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = settings.swift; sourceTree = ""; }; 9A998CD722A199920087ADE7 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 9A998CD922A199970087ADE7 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; }; 9A9D728924471FAE005CF997 /* SMC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMC.swift; sourceTree = ""; }; @@ -699,6 +701,7 @@ 9A81C7672449A43600825D92 /* main.swift */, 9A81C7682449A43600825D92 /* readers.swift */, 9AA6425F244B274200416A33 /* popup.swift */, + 9A953A1324B9D22D0038EF4B /* settings.swift */, 9A81C7592449A41400825D92 /* Info.plist */, 9AF9EE192464A7B3005D2270 /* config.plist */, ); @@ -1301,6 +1304,7 @@ files = ( 9A81C76A2449A43600825D92 /* readers.swift in Sources */, 9AA64260244B274200416A33 /* popup.swift in Sources */, + 9A953A1424B9D22D0038EF4B /* settings.swift in Sources */, 9A81C7692449A43600825D92 /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0;