From 5c85827abd47232f4dc3eaaa4f145d7cc47b1adc Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Wed, 6 Nov 2024 18:43:12 +0100 Subject: [PATCH] feat: added a Text widget to the RAM module --- Modules/RAM/config.plist | 7 ++++ Modules/RAM/main.swift | 47 +++++++++++++++++++++++++- Modules/RAM/readers.swift | 1 - Modules/RAM/settings.swift | 68 +++++++++++++++++++++++++++++++++++++- Modules/RAM/widget.swift | 1 - 5 files changed, 120 insertions(+), 4 deletions(-) diff --git a/Modules/RAM/config.plist b/Modules/RAM/config.plist index 83061491..ca0d9242 100644 --- a/Modules/RAM/config.plist +++ b/Modules/RAM/config.plist @@ -92,6 +92,13 @@ Order 6 + text + + Default + + Order + 7 + Settings diff --git a/Modules/RAM/main.swift b/Modules/RAM/main.swift index 8f95d7b5..aba63961 100644 --- a/Modules/RAM/main.swift +++ b/Modules/RAM/main.swift @@ -25,7 +25,6 @@ public struct RAM_Usage: Codable { var app: Double var cache: Double - var pressure: Double var rawPressureLevel: UInt var swap: Swap @@ -82,6 +81,10 @@ public class RAM: Module { return color.additional as! NSColor } + private var textValue: String { + Store.shared.string(key: "\(self.name)_textWidgetValue", defaultValue: "$mem.used/$mem.total ($pressure.value)") + } + public init() { self.settingsView = Settings(.RAM) self.popupView = Popup(.RAM) @@ -171,6 +174,48 @@ public class RAM: Module { circle_segment(value: value.wired/total, color: self.wiredColor), circle_segment(value: value.compressed/total, color: self.compressedColor) ]) + case let widget as TextWidget: + var text = self.textValue + let pairs = TextWidget.parseText(text) + pairs.forEach { pair in + var replacement: String? = nil + + switch pair.key { + case "$mem": + switch pair.value { + case "total": replacement = Units(bytes: Int64(value.total)).getReadableMemory() + case "used": replacement = Units(bytes: Int64(value.used)).getReadableMemory() + case "free": replacement = Units(bytes: Int64(value.free)).getReadableMemory() + case "active": replacement = Units(bytes: Int64(value.active)).getReadableMemory() + case "inactive": replacement = Units(bytes: Int64(value.inactive)).getReadableMemory() + case "wired": replacement = Units(bytes: Int64(value.wired)).getReadableMemory() + case "compressed": replacement = Units(bytes: Int64(value.compressed)).getReadableMemory() + case "app": replacement = Units(bytes: Int64(value.app)).getReadableMemory() + case "cache": replacement = Units(bytes: Int64(value.cache)).getReadableMemory() + default: return + } + case "$swap": + switch pair.value { + case "total": replacement = Units(bytes: Int64(value.swap.total)).getReadableMemory() + case "used": replacement = Units(bytes: Int64(value.swap.used)).getReadableMemory() + case "free": replacement = Units(bytes: Int64(value.swap.free)).getReadableMemory() + default: return + } + case "$pressure": + switch pair.value { + case "value": replacement = value.pressureLevel.description + case "level": replacement = value.rawPressureLevel.description + default: return + } + default: return + } + + if let replacement { + let key = pair.value.isEmpty ? pair.key : "\(pair.key).\(pair.value)" + text = text.replacingOccurrences(of: key, with: replacement) + } + } + widget.setValue(text) default: break } } diff --git a/Modules/RAM/readers.swift b/Modules/RAM/readers.swift index 69f1d6a2..ab34f321 100644 --- a/Modules/RAM/readers.swift +++ b/Modules/RAM/readers.swift @@ -76,7 +76,6 @@ internal class UsageReader: Reader { app: used - wired - compressed, cache: purgeable + external, - pressure: 100.0 * (wired + compressed) / self.totalSize, rawPressureLevel: UInt(pressureLevel), diff --git a/Modules/RAM/settings.swift b/Modules/RAM/settings.swift index fd90abf7..a92f3f8e 100644 --- a/Modules/RAM/settings.swift +++ b/Modules/RAM/settings.swift @@ -12,12 +12,41 @@ import Cocoa import Kit -internal class Settings: NSStackView, Settings_v { +var textWidgetHelp = """ +

Description

+You can use a combination of any of the variables. +

Examples:

+
    +
  • $mem.used/$mem.total ($pressure.value)
  • +
  • Pressure: $pressure.value
  • +
  • Free: $mem.free
  • +
+

Available variables

+
    +
  • $mem.total: Total RAM memory.
  • +
  • $mem.used: Used RAM memory.
  • +
  • $mem.free: Free RAM memory.
  • +
  • $mem.active: Active RAM memory.
  • +
  • $mem.inactive: Inactive RAM memory.
  • +
  • $mem.wired: Wired RAM memory.
  • +
  • $mem.compressed: Compressed RAM memory.
  • +
  • $mem.app: Used RAM memory by applications.
  • +
  • $mem.cache: Cached RAM memory.
  • +
  • $swap.total: Total swap memory.
  • +
  • $swap.used: Used swap memory.
  • +
  • $swap.free: Free swap memory.
  • +
  • $pressure.value: Pressure value (normal, warning, critical).
  • +
  • $pressure.level: Pressure level (1, 2, 4).
  • +
+""" + +internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate { private var updateIntervalValue: Int = 1 private var updateTopIntervalValue: Int = 1 private var numberOfProcesses: Int = 8 private var splitValueState: Bool = false private var notificationLevel: String = "Disabled" + private var textValue: String = "$mem.used/$mem.total ($pressure.value)" private let title: String @@ -26,6 +55,8 @@ internal class Settings: NSStackView, Settings_v { public var setInterval: ((_ value: Int) -> Void) = {_ in } public var setTopInterval: ((_ value: Int) -> Void) = {_ in } + private let textWidgetHelpPanel: HelpHUD = HelpHUD(textWidgetHelp) + public init(_ module: ModuleType) { self.title = module.rawValue self.updateIntervalValue = Store.shared.int(key: "\(self.title)_updateInterval", defaultValue: self.updateIntervalValue) @@ -77,6 +108,32 @@ internal class Settings: NSStackView, Settings_v { )) ])) } + + if widgets.contains(where: { $0 == .text }) { + let textField = self.inputField(id: "text", value: self.textValue, placeholder: localizedString("This will be visible in the text widget")) + self.addArrangedSubview(PreferencesSection([ + PreferencesRow(localizedString("Text widget value"), component: textField) { [weak self] in + self?.textWidgetHelpPanel.show() + } + ])) + } + } + + private func inputField(id: String, value: String, placeholder: String) -> NSView { + let field: NSTextField = NSTextField() + field.identifier = NSUserInterfaceItemIdentifier(id) + field.widthAnchor.constraint(equalToConstant: 250).isActive = true + field.font = NSFont.systemFont(ofSize: 12, weight: .regular) + field.textColor = .textColor + field.isEditable = true + field.isSelectable = true + field.usesSingleLineMode = true + field.maximumNumberOfLines = 1 + field.focusRingType = .none + field.stringValue = value + field.delegate = self + field.placeholderString = placeholder + return field } @objc private func changeUpdateInterval(_ sender: NSMenuItem) { @@ -105,4 +162,13 @@ internal class Settings: NSStackView, Settings_v { Store.shared.set(key: "\(self.title)_splitValue", value: self.splitValueState) self.callback() } + + func controlTextDidChange(_ notification: Notification) { + if let field = notification.object as? NSTextField { + if field.identifier == NSUserInterfaceItemIdentifier("text") { + self.textValue = field.stringValue + Store.shared.set(key: "\(self.title)_textWidgetValue", value: self.textValue) + } + } + } } diff --git a/Modules/RAM/widget.swift b/Modules/RAM/widget.swift index 55a066de..02ebbd78 100644 --- a/Modules/RAM/widget.swift +++ b/Modules/RAM/widget.swift @@ -27,7 +27,6 @@ public struct RAM_entry: TimelineEntry { compressed: 414629888.0, app: 16369778688.0, cache: 12575948800.0, - pressure: 7.636737823486328, rawPressureLevel: 1, swap: Swap(total: 0, used: 0, free: 0) )