From 3b9a9f4bd69a9d6d2a7b2f0aab794eabcde46413 Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Sat, 20 Jan 2024 19:05:12 +0100 Subject: [PATCH] feat: added details to the CPU portal view --- Kit/helpers.swift | 32 +++++++++ Kit/module/portal.swift | 44 ++++++++++++ Kit/plugins/Charts.swift | 23 ++++-- Modules/CPU/main.swift | 4 +- Modules/CPU/popup.swift | 48 ++----------- Modules/CPU/portal.swift | 150 +++++++++++++++++++++++---------------- 6 files changed, 190 insertions(+), 111 deletions(-) diff --git a/Kit/helpers.swift b/Kit/helpers.swift index ce70319b..24eafff2 100644 --- a/Kit/helpers.swift +++ b/Kit/helpers.swift @@ -261,6 +261,7 @@ public class LabelField: NSTextField { self.alignment = .natural self.font = NSFont.systemFont(ofSize: 12, weight: .regular) + self.cell?.truncatesLastVisibleLine = true self.cell?.usesSingleLineMode = true } @@ -374,6 +375,37 @@ public func popupWithColorRow(_ view: NSView, color: NSColor, n: CGFloat, title: return (colorView, labelView, valueView) } +public func portalWithColorRow(_ v: NSStackView, color: NSColor, title: String) -> (NSView, ValueField) { + let view: NSStackView = NSStackView() + view.orientation = .horizontal + view.distribution = .fillProportionally + view.spacing = 1 + + let colorView: NSView = NSView() + colorView.widthAnchor.constraint(equalToConstant: 5).isActive = true + colorView.wantsLayer = true + colorView.layer?.backgroundColor = color.cgColor + colorView.layer?.cornerRadius = 2 + + let labelView: LabelField = LabelField(title) + labelView.font = NSFont.systemFont(ofSize: 11, weight: .regular) + + let valueView: ValueField = ValueField() + valueView.font = NSFont.systemFont(ofSize: 12, weight: .regular) + valueView.widthAnchor.constraint(equalToConstant: 40).isActive = true + + view.addArrangedSubview(colorView) + view.addArrangedSubview(labelView) + view.addArrangedSubview(NSView()) + view.addArrangedSubview(valueView) + + v.addArrangedSubview(view) + + view.widthAnchor.constraint(equalTo: v.widthAnchor).isActive = true + + return (colorView, valueView) +} + public extension Array where Element: Equatable { func allEqual() -> Bool { if let firstElem = first { diff --git a/Kit/module/portal.swift b/Kit/module/portal.swift index cedb9877..06f76690 100644 --- a/Kit/module/portal.swift +++ b/Kit/module/portal.swift @@ -15,6 +15,50 @@ public protocol Portal_p: NSView { var name: String { get } } +open class PortalWrapper: NSStackView, Portal_p { + public var name: String + + private let header: PortalHeader + + public init(_ type: ModuleType, height: CGFloat = Constants.Popup.portalHeight) { + self.name = type.rawValue + self.header = PortalHeader(type.rawValue) + + super.init(frame: NSRect(x: 0, y: 0, width: Constants.Popup.width, height: height)) + + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor + self.layer?.cornerRadius = 3 + + self.orientation = .vertical + self.distribution = .fillEqually + self.spacing = Constants.Popup.spacing*2 + self.edgeInsets = NSEdgeInsets( + top: Constants.Popup.spacing*2, + left: Constants.Popup.spacing*2, + bottom: Constants.Popup.spacing*2, + right: Constants.Popup.spacing*2 + ) + self.addArrangedSubview(self.header) + + self.load() + + self.heightAnchor.constraint(equalToConstant: Constants.Popup.portalHeight).isActive = true + } + + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public override func updateLayer() { + self.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor + } + + open func load() { + self.addArrangedSubview(NSView()) + } +} + public class PortalHeader: NSStackView { private let name: String diff --git a/Kit/plugins/Charts.swift b/Kit/plugins/Charts.swift index a3e87664..f7f26ad9 100644 --- a/Kit/plugins/Charts.swift +++ b/Kit/plugins/Charts.swift @@ -829,7 +829,7 @@ public class TachometerGraphView: NSView { public class BarChartView: NSView { private var values: [ColorValue] = [] - public init(frame: NSRect, num: Int) { + public init(frame: NSRect = NSRect.zero, num: Int) { super.init(frame: frame) self.values = Array(repeating: ColorValue(0, color: .controlAccentColor), count: num) } @@ -858,17 +858,28 @@ public class BarChartView: NSView { let value = self.values[i] let color = value.color ?? .controlAccentColor let activeBlockNum = Int(round(value.value*Double(blocks))) + let h = value.value*partitionSize.height - var y: CGFloat = spacing - for b in 0.. NSView { + let view = NSStackView() + view.orientation = .vertical + view.distribution = .fillEqually + view.spacing = Constants.Popup.spacing*2 let circle = PieChartView(frame: NSRect.zero, segments: [], drawValue: true) circle.toolTip = localizedString("CPU usage") self.circle = circle - self.addArrangedSubview(circle) + view.addArrangedSubview(circle) if let cores = SystemKit.shared.device.info.cpu?.logicalCores { let barChartContainer: NSView = { - let box: NSStackView = NSStackView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: 30)) + let box: NSStackView = NSStackView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: 24)) box.heightAnchor.constraint(equalToConstant: box.frame.height).isActive = true box.wantsLayer = true box.layer?.backgroundColor = NSColor.lightGray.withAlphaComponent(0.1).cgColor box.layer?.cornerRadius = 3 - let chart = BarChartView(frame: NSRect( - x: Constants.Popup.spacing, - y: Constants.Popup.spacing, - width: Constants.Popup.width/2 - (Constants.Popup.spacing*2), - height: box.frame.height - (Constants.Popup.spacing*2) - ), num: Int(cores)) + let chart = BarChartView(num: Int(cores)) self.barChart = chart - box.addArrangedSubview(chart) return box }() - self.addArrangedSubview(barChartContainer) + view.addArrangedSubview(barChartContainer) } - self.heightAnchor.constraint(equalToConstant: Constants.Popup.portalHeight).isActive = true + return view } - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + private func details() -> NSView { + let view = NSStackView() + view.orientation = .vertical + view.distribution = .fillEqually + view.spacing = 2 + + (self.systemColorView, self.systemField) = portalWithColorRow(view, color: self.systemColor, title: "\(localizedString("System")):") + (self.userColorView, self.userField) = portalWithColorRow(view, color: self.userColor, title: "\(localizedString("User")):") + (self.idleColorView, self.idleField) = portalWithColorRow(view, color: self.idleColor.withAlphaComponent(0.5), title: "\(localizedString("Idle")):") + + if SystemKit.shared.device.info.cpu?.eCores != nil { + (self.eCoresColorView, self.eCoresField) = portalWithColorRow(view, color: self.eCoresColor, title: "E-cores:") + } + if SystemKit.shared.device.info.cpu?.pCores != nil { + (self.pCoresColorView, self.pCoresField) = portalWithColorRow(view, color: self.pCoresColor, title: "P-cores:") + } + + return view } - public override func updateLayer() { - self.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor - } - - public func loadCallback(_ value: CPU_Load) { + internal func callback(_ value: CPU_Load) { DispatchQueue.main.async(execute: { if (self.window?.isVisible ?? false) || !self.initialized { + self.systemField?.stringValue = "\(Int(value.systemLoad.rounded(toPlaces: 2) * 100))%" + self.userField?.stringValue = "\(Int(value.userLoad.rounded(toPlaces: 2) * 100))%" + self.idleField?.stringValue = "\(Int(value.idleLoad.rounded(toPlaces: 2) * 100))%" + self.circle?.setValue(value.totalUsage) self.circle?.setSegments([ circle_segment(value: value.systemLoad, color: self.systemColor), @@ -114,6 +135,13 @@ public class Portal: NSStackView, Portal_p { ]) self.circle?.setNonActiveSegmentColor(self.idleColor) + if let field = self.eCoresField, let usage = value.usageECores { + field.stringValue = "\(Int(usage * 100))%" + } + if let field = self.pCoresField, let usage = value.usagePCores { + field.stringValue = "\(Int(usage * 100))%" + } + var usagePerCore: [ColorValue] = [] if let cores = SystemKit.shared.device.info.cpu?.cores, cores.count == value.usagePerCore.count { for i in 0..