From 926838c52a403a5b3bd1b16e2e8e7e12422f8f41 Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Thu, 30 Mar 2023 18:29:12 +0200 Subject: [PATCH] feat: moved Sensors widget to the Stack_t (preparing for Sensors -> Stack widget migration) --- Kit/Widgets/Sensors.swift | 166 ++++++++++++++++++----------------- Kit/module/portal.swift | 2 +- Kit/types.swift | 12 ++- Modules/Bluetooth/main.swift | 4 +- Modules/Sensors/main.swift | 4 +- 5 files changed, 98 insertions(+), 90 deletions(-) diff --git a/Kit/Widgets/Sensors.swift b/Kit/Widgets/Sensors.swift index d570488f..3acd461b 100644 --- a/Kit/Widgets/Sensors.swift +++ b/Kit/Widgets/Sensors.swift @@ -11,33 +11,33 @@ import Cocoa -private struct Sensor_t: KeyValue_p { - let key: String - let name: String? - - var value: String - var additional: Any? +public struct Stack_t: KeyValue_p { + public var key: String + public var value: String + public var additional: Any? var index: Int { get { - return Store.shared.int(key: "sensors_\(self.key)_index", defaultValue: -1) + Store.shared.int(key: "stack_\(self.key)_index", defaultValue: -1) } set { - Store.shared.set(key: "sensors_\(self.key)_index", value: newValue) + Store.shared.set(key: "stack_\(self.key)_index", value: newValue) } } - init(key: String, value: String, name: String? = nil) { + public init(key: String, value: String, additional: Any? = nil) { self.key = key self.value = value - self.name = name + self.additional = additional } } public class SensorsWidget: WidgetWrapper { - private var modeState: String = "automatic" + private var modeState: StackMode = .auto private var fixedSizeState: Bool = false - private var values: [Sensor_t] = [] + private var monospacedFontState: Bool = false + + private var values: [Stack_t] = [] private var oneRowWidth: CGFloat = 38 private var twoRowWidth: CGFloat = 28 @@ -45,16 +45,11 @@ public class SensorsWidget: WidgetWrapper { private let orderTableView: OrderTableView public init(title: String, config: NSDictionary?, preview: Bool = false) { - if config != nil { - var configuration = config! - - if preview { - if let previewConfig = config!["Preview"] as? NSDictionary { - configuration = previewConfig - if let value = configuration["Values"] as? String { - for (i, value) in value.split(separator: ",").enumerated() { - self.values.append(Sensor_t(key: "\(i)", value: String(value))) - } + if let config, preview { + if let previewConfig = config["Preview"] as? NSDictionary { + if let value = previewConfig["Values"] as? String { + for (i, value) in value.split(separator: ",").enumerated() { + self.values.append(Stack_t(key: "\(i)", value: String(value))) } } } @@ -70,8 +65,9 @@ public class SensorsWidget: WidgetWrapper { )) if !preview { - self.modeState = Store.shared.string(key: "\(self.title)_\(self.type.rawValue)_mode", defaultValue: self.modeState) + self.modeState = StackMode(rawValue: Store.shared.string(key: "\(self.title)_\(self.type.rawValue)_mode", defaultValue: self.modeState.rawValue)) ?? .auto self.fixedSizeState = Store.shared.bool(key: "\(self.title)_\(self.type.rawValue)_size", defaultValue: self.fixedSizeState) + self.monospacedFontState = Store.shared.bool(key: "\(self.title)_\(self.type.rawValue)_monospacedFont", defaultValue: self.monospacedFontState) } self.orderTableView.reorderCallback = { [weak self] in @@ -98,15 +94,15 @@ public class SensorsWidget: WidgetWrapper { var i = 0 while i < self.values.count { switch self.modeState { - case "automatic", "twoRows": - let firstSensor: Sensor_t = self.values[i] - let secondSensor: Sensor_t? = self.values.indices.contains(i+1) ? self.values[i+1] : nil + case .auto, .twoRows: + let firstElement: Stack_t = self.values[i] + let secondElement: Stack_t? = self.values.indices.contains(i+1) ? self.values[i+1] : nil var width: CGFloat = 0 - if self.modeState == "automatic" && secondSensor == nil { - width += self.drawOneRow(firstSensor, x: x) + if self.modeState == .auto && secondElement == nil { + width += self.drawOneRow(x, firstElement) } else { - width += self.drawTwoRows(topSensor: firstSensor, bottomSensor: secondSensor, x: x) + width += self.drawTwoRows(x, firstElement, secondElement) } x += width @@ -118,8 +114,8 @@ public class SensorsWidget: WidgetWrapper { } i += 1 - case "oneRow": - let width = self.drawOneRow(self.values[i], x: x) + case .oneRow: + let width = self.drawOneRow(x, self.values[i]) x += width totalWidth += width @@ -129,31 +125,34 @@ public class SensorsWidget: WidgetWrapper { x += Constants.Widget.spacing totalWidth += Constants.Widget.spacing } - default: break } i += 1 } totalWidth += Constants.Widget.spacing // closing space - if abs(self.frame.width - totalWidth) < 2 { - return - } + guard abs(self.frame.width - totalWidth) > 2 else { return } self.setWidth(totalWidth) } - private func drawOneRow(_ sensor: Sensor_t, x: CGFloat) -> CGFloat { - let font: NSFont = NSFont.systemFont(ofSize: 13, weight: .regular) + private func drawOneRow(_ x: CGFloat, _ element: Stack_t) -> CGFloat { + var font: NSFont + if #available(macOS 10.15, *), self.monospacedFontState { + font = NSFont.monospacedSystemFont(ofSize: 13, weight: .regular) + } else { + font = NSFont.systemFont(ofSize: 13, weight: .regular) + } + let style = NSMutableParagraphStyle() style.alignment = .center var width: CGFloat = self.oneRowWidth if !self.fixedSizeState { - width = sensor.value.widthOfString(usingFont: font).rounded(.up) + 2 + width = element.value.widthOfString(usingFont: font).rounded(.up) + 2 } let rect = CGRect(x: x, y: (Constants.Widget.height-13)/2, width: width, height: 13) - let str = NSAttributedString.init(string: sensor.value, attributes: [ + let str = NSAttributedString.init(string: element.value, attributes: [ NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: NSColor.textColor, NSAttributedString.Key.paragraphStyle: style @@ -163,10 +162,15 @@ public class SensorsWidget: WidgetWrapper { return width } - private func drawTwoRows(topSensor: Sensor_t, bottomSensor: Sensor_t?, x: CGFloat) -> CGFloat { + private func drawTwoRows(_ x: CGFloat, _ topElement: Stack_t, _ bottomElement: Stack_t?) -> CGFloat { let rowHeight: CGFloat = self.frame.height / 2 - let font: NSFont = NSFont.systemFont(ofSize: 10, weight: .light) + var font: NSFont + if #available(macOS 10.15, *), self.monospacedFontState { + font = NSFont.monospacedSystemFont(ofSize: 10, weight: .light) + } else { + font = NSFont.systemFont(ofSize: 10, weight: .light) + } let style = NSMutableParagraphStyle() style.alignment = .right @@ -178,34 +182,34 @@ public class SensorsWidget: WidgetWrapper { var width: CGFloat = self.twoRowWidth if !self.fixedSizeState { - let firstRowWidth = topSensor.value.widthOfString(usingFont: font) - let secondRowWidth = bottomSensor?.value.widthOfString(usingFont: font) ?? 0 + let firstRowWidth = topElement.value.widthOfString(usingFont: font) + let secondRowWidth = bottomElement?.value.widthOfString(usingFont: font) ?? 0 width = max(20, max(firstRowWidth, secondRowWidth)).rounded(.up) + 2 } var rect = CGRect(x: x, y: rowHeight+1, width: width, height: rowHeight) - var str = NSAttributedString.init(string: topSensor.value, attributes: attributes) + var str = NSAttributedString.init(string: topElement.value, attributes: attributes) str.draw(with: rect) - if bottomSensor != nil { + if bottomElement != nil { rect = CGRect(x: x, y: 1, width: width, height: rowHeight) - str = NSAttributedString.init(string: bottomSensor!.value, attributes: attributes) + str = NSAttributedString.init(string: bottomElement!.value, attributes: attributes) str.draw(with: rect) } return width } - public func setValues(_ values: [KeyValue_t]) { + public func setValues(_ values: [Stack_t]) { var tableNeedsToBeUpdated: Bool = false - values.forEach { (p: KeyValue_t) in + values.forEach { (p: Stack_t) in if let idx = self.values.firstIndex(where: { $0.key == p.key }) { self.values[idx].value = p.value return } tableNeedsToBeUpdated = true - self.values.append(Sensor_t(key: p.key, value: p.value, name: p.additional as? String)) + self.values.append(p) } let diff = self.values.filter({ v in values.contains(where: { $0.key == v.key }) }) @@ -218,7 +222,7 @@ public class SensorsWidget: WidgetWrapper { if tableNeedsToBeUpdated { self.orderTableView.update() } - self.needsDisplay = true + self.display() }) } @@ -241,9 +245,6 @@ public class SensorsWidget: WidgetWrapper { line.lineWidth = lineWidth line.stroke() - if abs(self.frame.width - totalWidth) < 2 { - return - } self.setWidth(totalWidth) } @@ -256,14 +257,24 @@ public class SensorsWidget: WidgetWrapper { title: localizedString("Display mode"), action: #selector(changeMode), items: SensorsWidgetMode, - selected: self.modeState + selected: self.modeState.rawValue )) - view.addArrangedSubview(toggleSettingRow( - title: localizedString("Static width"), - action: #selector(toggleSize), - state: self.fixedSizeState - )) + if self.title != "Clock" { + view.addArrangedSubview(toggleSettingRow( + title: localizedString("Static width"), + action: #selector(toggleSize), + state: self.fixedSizeState + )) + } + + if #available(macOS 10.15, *) { + view.addArrangedSubview(toggleSettingRow( + title: localizedString("Monospaced font"), + action: #selector(toggleMonospacedFont), + state: self.monospacedFontState + )) + } view.addArrangedSubview(self.orderTableView) @@ -271,24 +282,23 @@ public class SensorsWidget: WidgetWrapper { } @objc private func changeMode(_ sender: NSMenuItem) { - guard let key = sender.representedObject as? String else { - return - } - self.modeState = key + guard let key = sender.representedObject as? String else { return } + self.modeState = StackMode(rawValue: key) ?? .auto Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_mode", value: key) + self.display() } @objc private func toggleSize(_ sender: NSControl) { - var state: NSControl.StateValue? = nil - if #available(OSX 10.15, *) { - state = sender is NSSwitch ? (sender as! NSSwitch).state: nil - } else { - state = sender is NSButton ? (sender as! NSButton).state: nil - } - self.fixedSizeState = state! == .on ? true : false + self.fixedSizeState = controlState(sender) Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_size", value: self.fixedSizeState) self.display() } + + @objc private func toggleMonospacedFont(_ sender: NSControl) { + self.monospacedFontState = controlState(sender) + Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_monospacedFont", value: self.monospacedFontState) + self.display() + } } private class OrderTableView: NSView, NSTableViewDelegate, NSTableViewDataSource { @@ -297,9 +307,9 @@ private class OrderTableView: NSView, NSTableViewDelegate, NSTableViewDataSource private var dragDropType = NSPasteboard.PasteboardType(rawValue: "\(Bundle.main.bundleIdentifier!).sensors-row") public var reorderCallback: () -> Void = {} - private let list: UnsafeMutablePointer<[Sensor_t]> + private let list: UnsafeMutablePointer<[Stack_t]> - init(_ list: UnsafeMutablePointer<[Sensor_t]>) { + init(_ list: UnsafeMutablePointer<[Stack_t]>) { self.list = list super.init(frame: NSRect.zero) @@ -328,12 +338,7 @@ private class OrderTableView: NSView, NSTableViewDelegate, NSTableViewDataSource self.tableView.style = .plain } - let colKey = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue: "key")) - colKey.width = 50 - let colName = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue: "name")) - - self.tableView.addTableColumn(colName) - self.tableView.addTableColumn(colKey) + self.tableView.addTableColumn(NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue: "name"))) self.addSubview(self.scrollView) @@ -376,10 +381,7 @@ private class OrderTableView: NSView, NSTableViewDelegate, NSTableViewDataSource text.identifier = NSUserInterfaceItemIdentifier(item.key) switch tableColumn?.identifier.rawValue { - case "key": - text.stringValue = item.key - case "name": - text.stringValue = "\(item.name ?? localizedString("Unknown"))" + case "name": text.stringValue = item.key default: break } diff --git a/Kit/module/portal.swift b/Kit/module/portal.swift index 4cebc5f7..e8b4687e 100644 --- a/Kit/module/portal.swift +++ b/Kit/module/portal.swift @@ -12,5 +12,5 @@ import Cocoa public protocol Portal_p: NSView { - var name: String { get set } + var name: String { get } } diff --git a/Kit/types.swift b/Kit/types.swift index e7f831dc..efb57eb1 100644 --- a/Kit/types.swift +++ b/Kit/types.swift @@ -83,11 +83,17 @@ public let SpeedBase: [KeyValue_t] = [ KeyValue_t(key: "byte", value: "Byte", additional: DataSizeBase.byte) ] +public enum StackMode: String { + case auto = "automatic" + case oneRow = "oneRow" + case twoRows = "twoRows" +} + public let SensorsWidgetMode: [KeyValue_t] = [ - KeyValue_t(key: "automatic", value: "Automatic"), + KeyValue_t(key: StackMode.auto.rawValue, value: "Automatic"), KeyValue_t(key: "separator", value: "separator"), - KeyValue_t(key: "oneRow", value: "One row"), - KeyValue_t(key: "twoRows", value: "Two rows") + KeyValue_t(key: StackMode.oneRow.rawValue, value: "One row"), + KeyValue_t(key: StackMode.twoRows.rawValue, value: "Two rows") ] public let SpeedPictogram: [KeyValue_t] = [ diff --git a/Modules/Bluetooth/main.swift b/Modules/Bluetooth/main.swift index 6079ab45..01a009a2 100644 --- a/Modules/Bluetooth/main.swift +++ b/Modules/Bluetooth/main.swift @@ -77,11 +77,11 @@ public class Bluetooth: Module { self.settingsView.setList(active) }) - var list: [KeyValue_t] = [] + var list: [Stack_t] = [] active.forEach { (d: BLEDevice) in if d.state { d.batteryLevel.forEach { (p: KeyValue_t) in - list.append(KeyValue_t(key: "\(d.address)-\(p.key)", value: "\(p.value)%")) + list.append(Stack_t(key: "\(d.address)-\(p.key)", value: "\(p.value)%")) } } } diff --git a/Modules/Sensors/main.swift b/Modules/Sensors/main.swift index 8f9b81f1..fa63eb50 100644 --- a/Modules/Sensors/main.swift +++ b/Modules/Sensors/main.swift @@ -96,7 +96,7 @@ public class Sensors: Module { return } - var list: [KeyValue_t] = [] + var list: [Stack_t] = [] var flatList: [[ColorValue]] = [] value.forEach { (s: Sensor_p) in @@ -108,7 +108,7 @@ public class Sensors: Module { value = "\(f.percentage)%" } } - list.append(KeyValue_t(key: s.key, value: value, additional: s.name)) + list.append(Stack_t(key: s.key, value: value, additional: s.name)) } }