feat: added a new Text widget that allows to visualize custom values in the menu bar

This commit is contained in:
Serhiy Mytrovtsiy
2024-09-10 18:14:46 +02:00
parent c52d0e23b5
commit 4b213c4392
3 changed files with 97 additions and 0 deletions

88
Kit/Widgets/Text.swift Normal file
View File

@@ -0,0 +1,88 @@
//
// Text.swift
// Kit
//
// Created by Serhiy Mytrovtsiy on 08/09/2024
// Using Swift 5.0
// Running on macOS 14.6
//
// Copyright © 2024 Serhiy Mytrovtsiy. All rights reserved.
//
import Cocoa
public class TextWidget: WidgetWrapper {
private var value: String = ""
public init(title: String, config: NSDictionary?, preview: Bool = false) {
super.init(.text, title: title, frame: CGRect(
x: 0,
y: Constants.Widget.margin.y,
width: 30 + (2*Constants.Widget.margin.x),
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
))
if preview {
self.value = "Text"
}
self.canDrawConcurrently = true
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
var value: String = ""
self.queue.sync {
value = self.value
}
if value.isEmpty {
self.setWidth(0)
return
}
let valueSize: CGFloat = 12
let style = NSMutableParagraphStyle()
style.alignment = .center
let stringAttributes = [
NSAttributedString.Key.font: NSFont.systemFont(ofSize: valueSize, weight: .regular),
NSAttributedString.Key.foregroundColor: NSColor.textColor,
NSAttributedString.Key.paragraphStyle: style
]
let attributedString = NSAttributedString(string: value, attributes: stringAttributes)
let size = attributedString.boundingRect(
with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude),
options: [.usesLineFragmentOrigin, .usesFontLeading]
)
let width = (size.width+Constants.Widget.margin.x*2).roundedUpToNearestTen()
let origin: CGPoint = CGPoint(x: Constants.Widget.margin.x, y: ((Constants.Widget.height-valueSize-1)/2))
let rect = CGRect(x: origin.x, y: origin.y, width: width - (Constants.Widget.margin.x*2), height: valueSize)
attributedString.draw(with: rect)
self.setWidth(width)
}
public func setValue(_ newValue: String) {
guard self.value != newValue else { return }
self.value = newValue
DispatchQueue.main.async(execute: {
self.display()
})
}
static public func parseText(_ raw: String) -> [KeyValue_t] {
var pairs: [KeyValue_t] = []
raw.split(separator: " ", omittingEmptySubsequences: true).filter({ $0.hasPrefix("$") }).forEach { v in
let arr = v.split(separator: ".", omittingEmptySubsequences: true)
guard let key = arr.first else { return }
let value = arr.count == 1 ? nil : arr.last
pairs.append(KeyValue_t(key: String(key), value: String(value ?? "")))
}
return pairs
}
}

View File

@@ -26,6 +26,7 @@ public enum widget_t: String {
case label = "label"
case tachometer = "tachometer"
case state = "state"
case text = "text"
public func new(module: String, config: NSDictionary, defaultWidget: widget_t) -> SWidget? {
guard let widgetConfig: NSDictionary = config[self.rawValue] as? NSDictionary else { return nil }
@@ -74,6 +75,9 @@ public enum widget_t: String {
case .state:
preview = StateWidget(title: module, config: widgetConfig, preview: true)
item = StateWidget(title: module, config: widgetConfig, preview: false)
case .text:
preview = TextWidget(title: module, config: widgetConfig, preview: true)
item = TextWidget(title: module, config: widgetConfig, preview: false)
default: break
}
@@ -137,6 +141,7 @@ public enum widget_t: String {
case .label: return localizedString("Label widget")
case .tachometer: return localizedString("Tachometer widget")
case .state: return localizedString("State widget")
case .text: return localizedString("Text widget")
default: return ""
}
}