diff --git a/Modules/CPU/popup.swift b/Modules/CPU/popup.swift index 91526aa0..3385ff77 100644 --- a/Modules/CPU/popup.swift +++ b/Modules/CPU/popup.swift @@ -86,9 +86,7 @@ internal class Popup: NSView { DispatchQueue.main.async(execute: { self.subviews.forEach{ $0.removeFromSuperview() } - self.processes.forEach { (p: ProcessView) in - p.removeFromSuperview() - } + self.processes = [] let h: CGFloat = self.dashboardHeight + self.chartHeight + self.detailsHeight + (self.processHeight*CGFloat(self.numberOfProcesses)) + (Constants.Popup.separatorHeight*3) self.setFrameSize(NSSize(width: self.frame.width, height: h)) diff --git a/Modules/Memory/main.swift b/Modules/Memory/main.swift index f8211445..01f7fed9 100644 --- a/Modules/Memory/main.swift +++ b/Modules/Memory/main.swift @@ -34,13 +34,14 @@ public struct RAM_Usage: value_t { } public class Memory: Module { - private let popupView: Popup = Popup() + private var settingsView: Settings + private let popupView: Popup private var usageReader: UsageReader? = nil private var processReader: ProcessReader? = nil - private var settingsView: Settings public init(_ store: UnsafePointer) { self.settingsView = Settings("RAM", store: store) + self.popupView = Popup("RAM", store: store) super.init( store: store, @@ -50,11 +51,16 @@ public class Memory: Module { guard self.available else { return } self.settingsView.setInterval = { [unowned self] value in + self.processReader?.read() self.usageReader?.setInterval(value) } self.usageReader = UsageReader() - self.processReader = ProcessReader() + self.processReader = ProcessReader(self.config.name, store: store) + + self.settingsView.callbackWhenUpdateNumberOfProcesses = { + self.popupView.numberOfProcessesUpdated() + } self.usageReader?.readyCallback = { [unowned self] in self.readyHandler() diff --git a/Modules/Memory/popup.swift b/Modules/Memory/popup.swift index 20b78977..82f5373d 100644 --- a/Modules/Memory/popup.swift +++ b/Modules/Memory/popup.swift @@ -14,10 +14,13 @@ import ModuleKit import StatsKit internal class Popup: NSView { + private var store: UnsafePointer + private var title: String + private let dashboardHeight: CGFloat = 90 private let chartHeight: CGFloat = 90 private let detailsHeight: CGFloat = 22*6 - private let processesHeight: CGFloat = 22*5 + private let processHeight: CGFloat = 22 private var totalField: NSTextField? = nil private var usedField: NSTextField? = nil @@ -36,18 +39,36 @@ internal class Popup: NSView { private var processes: [ProcessView] = [] - public init() { + private var numberOfProcesses: Int { + get { + return self.store.pointee.int(key: "\(self.title)_processes", defaultValue: 8) + } + } + + public init(_ title: String, store: UnsafePointer) { + self.store = store + self.title = title + super.init(frame: NSRect( x: 0, y: 0, width: Constants.Popup.width, - height: dashboardHeight + chartHeight + detailsHeight + processesHeight + (Constants.Popup.separatorHeight*3) + height: dashboardHeight + chartHeight + detailsHeight + (Constants.Popup.separatorHeight*3) )) - initDashboard() - initChart() - initDetails() - initProcesses() + let h: CGFloat = self.dashboardHeight + self.chartHeight + self.detailsHeight + (self.processHeight*CGFloat(self.numberOfProcesses)) + (Constants.Popup.separatorHeight*3) + self.setFrameSize(NSSize(width: self.frame.width, height: h)) + + self.initDashboard() + self.initChart() + self.initDetails() + self.initProcesses() + + DispatchQueue.main.async(execute: { + if self.frame.size.height != h { + NotificationCenter.default.post(name: .updatePopupSize, object: nil, userInfo: ["module": self.title]) + } + }) } required init?(coder: NSCoder) { @@ -58,6 +79,27 @@ internal class Popup: NSView { self.chart?.display() } + public func numberOfProcessesUpdated() { + if self.processes.count == self.numberOfProcesses { + return + } + + DispatchQueue.main.async(execute: { + self.subviews.forEach{ $0.removeFromSuperview() } + self.processes = [] + + let h: CGFloat = self.dashboardHeight + self.chartHeight + self.detailsHeight + (self.processHeight*CGFloat(self.numberOfProcesses)) + (Constants.Popup.separatorHeight*3) + self.setFrameSize(NSSize(width: self.frame.width, height: h)) + + self.initDashboard() + self.initChart() + self.initDetails() + self.initProcesses() + + NotificationCenter.default.post(name: .updatePopupSize, object: nil, userInfo: ["module": self.title]) + }) + } + private func initDashboard() { let view: NSView = NSView(frame: NSRect(x: 0, y: self.frame.height - self.dashboardHeight, width: self.frame.width, height: self.dashboardHeight)) view.wantsLayer = true @@ -114,16 +156,15 @@ internal class Popup: NSView { } private func initProcesses() { - let separator = SeparatorView(LocalizedString("Top processes"), origin: NSPoint(x: 0, y: self.processesHeight), width: self.frame.width) + let height: CGFloat = self.processHeight*CGFloat(self.numberOfProcesses) + let separator = SeparatorView(LocalizedString("Top processes"), origin: NSPoint(x: 0, y: height), width: self.frame.width) self.addSubview(separator) - let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.processesHeight)) + let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: height)) - self.processes.append(ProcessView(0)) - self.processes.append(ProcessView(1)) - self.processes.append(ProcessView(2)) - self.processes.append(ProcessView(3)) - self.processes.append(ProcessView(4)) + for i in 0...self.numberOfProcesses { + self.processes.append(ProcessView(CGFloat(i))) + } self.processes.forEach{ view.addSubview($0) } diff --git a/Modules/Memory/readers.swift b/Modules/Memory/readers.swift index bf25fdf9..127002b0 100644 --- a/Modules/Memory/readers.swift +++ b/Modules/Memory/readers.swift @@ -80,6 +80,21 @@ internal class UsageReader: Reader { } public class ProcessReader: Reader<[TopProcess]> { + private let store: UnsafePointer + private let title: String + + private var numberOfProcesses: Int { + get { + return self.store.pointee.int(key: "\(self.title)_processes", defaultValue: 8) + } + } + + init(_ title: String, store: UnsafePointer) { + self.title = title + self.store = store + super.init() + } + public override func setup() { self.popup = true } @@ -87,7 +102,7 @@ public class ProcessReader: Reader<[TopProcess]> { public override func read() { let task = Process() task.launchPath = "/usr/bin/top" - task.arguments = ["-l", "1", "-o", "mem", "-n", "5", "-stats", "pid,command,mem"] + task.arguments = ["-l", "1", "-o", "mem", "-n", "\(self.numberOfProcesses)", "-stats", "pid,command,mem"] let outputPipe = Pipe() let errorPipe = Pipe() diff --git a/Modules/Memory/settings.swift b/Modules/Memory/settings.swift index 861c8fa0..fa996a38 100644 --- a/Modules/Memory/settings.swift +++ b/Modules/Memory/settings.swift @@ -15,17 +15,20 @@ import ModuleKit internal class Settings: NSView, Settings_v { private var updateIntervalValue: Int = 1 + private var numberOfProcesses: Int = 8 private let title: String private let store: UnsafePointer public var callback: (() -> Void) = {} + public var callbackWhenUpdateNumberOfProcesses: (() -> Void) = {} public var setInterval: ((_ value: Int) -> Void) = {_ in } public init(_ title: String, store: UnsafePointer) { self.title = title self.store = store self.updateIntervalValue = store.pointee.int(key: "\(self.title)_updateInterval", defaultValue: self.updateIntervalValue) + self.numberOfProcesses = store.pointee.int(key: "\(self.title)_processes", defaultValue: self.numberOfProcesses) super.init(frame: CGRect( x: 0, @@ -46,7 +49,7 @@ internal class Settings: NSView, Settings_v { self.subviews.forEach{ $0.removeFromSuperview() } let rowHeight: CGFloat = 30 - let num: CGFloat = 0 + let num: CGFloat = 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), @@ -56,6 +59,14 @@ internal class Settings: NSView, Settings_v { selected: "\(self.updateIntervalValue) sec" )) + self.addSubview(SelectTitleRow( + frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin, width: self.frame.width - (Constants.Settings.margin*2), height: rowHeight), + title: LocalizedString("Number of top processes"), + action: #selector(changeNumberOfProcesses), + items: NumbersOfProcesses.map{ "\($0)" }, + selected: "\(self.numberOfProcesses)" + )) + self.setFrameSize(NSSize(width: self.frame.width, height: (rowHeight*(num+1)) + (Constants.Settings.margin*(2+num)))) } @@ -66,4 +77,12 @@ internal class Settings: NSView, Settings_v { self.setInterval(value) } } + + @objc private func changeNumberOfProcesses(_ sender: NSMenuItem) { + if let value = Int(sender.title) { + self.numberOfProcesses = value + self.store.pointee.set(key: "\(self.title)_processes", value: value) + self.callbackWhenUpdateNumberOfProcesses() + } + } }