feat: added a Text widget to the RAM module

This commit is contained in:
Serhiy Mytrovtsiy
2024-11-06 18:43:12 +01:00
parent 9f2135f41a
commit 5c85827abd
5 changed files with 120 additions and 4 deletions

View File

@@ -92,6 +92,13 @@
<key>Order</key>
<integer>6</integer>
</dict>
<key>text</key>
<dict>
<key>Default</key>
<false/>
<key>Order</key>
<integer>7</integer>
</dict>
</dict>
<key>Settings</key>
<dict>

View File

@@ -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
}
}

View File

@@ -76,7 +76,6 @@ internal class UsageReader: Reader<RAM_Usage> {
app: used - wired - compressed,
cache: purgeable + external,
pressure: 100.0 * (wired + compressed) / self.totalSize,
rawPressureLevel: UInt(pressureLevel),

View File

@@ -12,12 +12,41 @@
import Cocoa
import Kit
internal class Settings: NSStackView, Settings_v {
var textWidgetHelp = """
<h2>Description</h2>
You can use a combination of any of the variables.
<h3>Examples:</h3>
<ul>
<li>$mem.used/$mem.total ($pressure.value)</li>
<li>Pressure: $pressure.value</li>
<li>Free: $mem.free</li>
</ul>
<h2>Available variables</h2>
<ul>
<li><b>$mem.total</b>: <small>Total RAM memory.</small></li>
<li><b>$mem.used</b>: <small>Used RAM memory.</small></li>
<li><b>$mem.free</b>: <small>Free RAM memory.</small></li>
<li><b>$mem.active</b>: <small>Active RAM memory.</small></li>
<li><b>$mem.inactive</b>: <small>Inactive RAM memory.</small></li>
<li><b>$mem.wired</b>: <small>Wired RAM memory.</small></li>
<li><b>$mem.compressed</b>: <small>Compressed RAM memory.</small></li>
<li><b>$mem.app</b>: <small>Used RAM memory by applications.</small></li>
<li><b>$mem.cache</b>: <small>Cached RAM memory.</small></li>
<li><b>$swap.total</b>: <small>Total swap memory.</small></li>
<li><b>$swap.used</b>: <small>Used swap memory.</small></li>
<li><b>$swap.free</b>: <small>Free swap memory.</small></li>
<li><b>$pressure.value</b>: <small>Pressure value (normal, warning, critical).</small></li>
<li><b>$pressure.level</b>: <small>Pressure level (1, 2, 4).</small></li>
</ul>
"""
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)
}
}
}
}

View File

@@ -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)
)