diff --git a/ModuleKit/Widgets/Sensors.swift b/ModuleKit/Widgets/Sensors.swift index f9c6891a..02e079fd 100644 --- a/ModuleKit/Widgets/Sensors.swift +++ b/ModuleKit/Widgets/Sensors.swift @@ -83,7 +83,7 @@ public class SensorsWidget: Widget { font = NSFont.monospacedSystemFont(ofSize: 9, weight: .light) } let style = NSMutableParagraphStyle() - style.alignment = .center + style.alignment = .right let firstRowWidth = self.values[i*2].value.widthOfString(usingFont: font) let secondRowWidth = self.values[(i*2)+1].value.widthOfString(usingFont: font) @@ -100,7 +100,6 @@ public class SensorsWidget: Widget { paddingLeft = iconSize + (Constants.Widget.margin*3) width += paddingLeft - style.alignment = .right } let attributes = [ diff --git a/ModuleKit/popup.swift b/ModuleKit/popup.swift index b6f6ed86..4024949c 100644 --- a/ModuleKit/popup.swift +++ b/ModuleKit/popup.swift @@ -155,7 +155,6 @@ internal class PopupView: NSView { } internal func disappear() {} - @objc private func listenChangingPopupSize(_ notification: Notification) { if let moduleName = notification.userInfo?["module"] as? String, moduleName == self.title { self.updateLayer() diff --git a/Modules/CPU/popup.swift b/Modules/CPU/popup.swift index 3385ff77..cafb0010 100644 --- a/Modules/CPU/popup.swift +++ b/Modules/CPU/popup.swift @@ -17,9 +17,11 @@ internal class Popup: NSView { private var store: UnsafePointer private var title: String + private var grid: NSGridView? = nil + private let dashboardHeight: CGFloat = 90 - private let chartHeight: CGFloat = 90 - private let detailsHeight: CGFloat = 22*3 + private let chartHeight: CGFloat = 90 + Constants.Popup.separatorHeight + private let detailsHeight: CGFloat = (22*3) + Constants.Popup.separatorHeight private let processHeight: CGFloat = 22 private var loadField: NSTextField? = nil @@ -44,6 +46,11 @@ internal class Popup: NSView { return self.store.pointee.int(key: "\(self.title)_processes", defaultValue: 8) } } + private var processesHeight: CGFloat { + get { + return (self.processHeight*CGFloat(self.numberOfProcesses))+Constants.Popup.separatorHeight + } + } public init(_ title: String, store: UnsafePointer) { self.store = store @@ -53,22 +60,25 @@ internal class Popup: NSView { x: 0, y: 0, width: Constants.Popup.width, - height: dashboardHeight + chartHeight + detailsHeight + (Constants.Popup.separatorHeight*3) + height: self.dashboardHeight + self.chartHeight + self.detailsHeight )) + self.setFrameSize(NSSize(width: self.frame.width, height: self.frame.height+self.processesHeight)) - let h: CGFloat = self.dashboardHeight + self.chartHeight + self.detailsHeight + (self.processHeight*CGFloat(self.numberOfProcesses)) + (Constants.Popup.separatorHeight*3) - self.setFrameSize(NSSize(width: self.frame.width, height: h)) + let gridView: NSGridView = NSGridView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)) + gridView.rowSpacing = 0 + gridView.yPlacement = .fill - initDashboard() - initChart() - initDetails() - initProcesses() + gridView.addRow(with: [self.initDashboard()]) + gridView.addRow(with: [self.initChart()]) + gridView.addRow(with: [self.initDetails()]) + gridView.addRow(with: [self.initProcesses()]) - DispatchQueue.main.async(execute: { - if self.frame.size.height != h { - NotificationCenter.default.post(name: .updatePopupSize, object: nil, userInfo: ["module": self.title]) - } - }) + gridView.row(at: 0).height = self.dashboardHeight + gridView.row(at: 1).height = self.chartHeight + gridView.row(at: 2).height = self.detailsHeight + + self.addSubview(gridView) + self.grid = gridView } required init?(coder: NSCoder) { @@ -85,24 +95,24 @@ internal class Popup: NSView { } DispatchQueue.main.async(execute: { - self.subviews.forEach{ $0.removeFromSuperview() } self.processes = [] - let h: CGFloat = self.dashboardHeight + self.chartHeight + self.detailsHeight + (self.processHeight*CGFloat(self.numberOfProcesses)) + (Constants.Popup.separatorHeight*3) + let h: CGFloat = self.dashboardHeight + self.chartHeight + self.detailsHeight + self.processesHeight self.setFrameSize(NSSize(width: self.frame.width, height: h)) - self.initDashboard() - self.initChart() - self.initDetails() - self.initProcesses() - NotificationCenter.default.post(name: .updatePopupSize, object: nil, userInfo: ["module": self.title]) + + self.grid?.setFrameSize(NSSize(width: self.frame.width, height: h)) + + self.grid?.row(at: 3).cell(at: 0).contentView?.removeFromSuperview() + self.grid?.removeRow(at: 3) + self.grid?.addRow(with: [self.initProcesses()]) + self.processesInitialized = false }) } - private func initDashboard() { - let view: NSView = NSView(frame: NSRect(x: 0, y: self.frame.height - self.dashboardHeight, width: self.frame.width, height: self.dashboardHeight)) - view.wantsLayer = true + private func initDashboard() -> NSView { + let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.dashboardHeight)) let container: NSView = NSView(frame: NSRect(x: 0, y: 10, width: view.frame.width, height: self.dashboardHeight-20)) self.circle = CircleGraphView(frame: NSRect(x: (container.frame.width - container.frame.height)/2, y: 0, width: container.frame.height, height: container.frame.height), segments: []) @@ -122,75 +132,56 @@ internal class Popup: NSView { view.addSubview(container) view.addSubview(self.frequencyCircle!) - self.addSubview(view) + return view } - private func initChart() { - let y: CGFloat = self.frame.height - self.dashboardHeight - Constants.Popup.separatorHeight - let separator = SeparatorView(LocalizedString("Usage history"), origin: NSPoint(x: 0, y: y), width: self.frame.width) - self.addSubview(separator) - - let view: NSView = NSView(frame: NSRect(x: 0, y: y - self.chartHeight, width: self.frame.width, height: self.chartHeight)) - view.wantsLayer = true - view.layer?.backgroundColor = NSColor.lightGray.withAlphaComponent(0.1).cgColor - view.layer?.cornerRadius = 3 + private func initChart() -> NSView { + let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.chartHeight)) + let separator = SeparatorView(LocalizedString("Usage history"), origin: NSPoint(x: 0, y: self.chartHeight-Constants.Popup.separatorHeight), width: self.frame.width) + let container: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: separator.frame.origin.y)) + container.wantsLayer = true + container.layer?.backgroundColor = NSColor.lightGray.withAlphaComponent(0.1).cgColor + container.layer?.cornerRadius = 3 self.chart = LineChartView(frame: NSRect(x: 1, y: 0, width: view.frame.width, height: view.frame.height), num: 120) + container.addSubview(self.chart!) - view.addSubview(self.chart!) + view.addSubview(separator) + view.addSubview(container) - self.addSubview(view) + return view } - private func initDetails() { - let y: CGFloat = self.frame.height - self.dashboardHeight - self.chartHeight - (Constants.Popup.separatorHeight*2) - let separator = SeparatorView(LocalizedString("Details"), origin: NSPoint(x: 0, y: y), width: self.frame.width) - self.addSubview(separator) + private func initDetails() -> NSView { + let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.detailsHeight)) + let separator = SeparatorView(LocalizedString("Details"), origin: NSPoint(x: 0, y: self.detailsHeight-Constants.Popup.separatorHeight), width: self.frame.width) + let container: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: separator.frame.origin.y)) - let view: NSView = NSView(frame: NSRect(x: 0, y: separator.frame.origin.y - self.detailsHeight, width: self.frame.width, height: self.detailsHeight)) + self.systemField = PopupWithColorRow(container, color: NSColor.systemRed, n: 2, title: "\(LocalizedString("System")):", value: "") + self.userField = PopupWithColorRow(container, color: NSColor.systemBlue, n: 1, title: "\(LocalizedString("User")):", value: "") + self.idleField = PopupWithColorRow(container, color: NSColor.lightGray.withAlphaComponent(0.5), n: 0, title: "\(LocalizedString("Idle")):", value: "") - self.systemField = PopupWithColorRow(view, color: NSColor.systemRed, n: 2, title: "\(LocalizedString("System")):", value: "") - self.userField = PopupWithColorRow(view, color: NSColor.systemBlue, n: 1, title: "\(LocalizedString("User")):", value: "") - self.idleField = PopupWithColorRow(view, color: NSColor.lightGray.withAlphaComponent(0.5), n: 0, title: "\(LocalizedString("Idle")):", value: "") + view.addSubview(separator) + view.addSubview(container) - self.addSubview(view) + return view } - private func initProcesses() { - let height: CGFloat = self.processHeight*CGFloat(self.numberOfProcesses) - let separator = SeparatorView(LocalizedString("Top processes"), origin: NSPoint(x: 0, y: height), width: self.frame.width) - self.addSubview(separator) - - let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: height)) + private func initProcesses() -> NSView { + let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.processesHeight)) + let separator = SeparatorView(LocalizedString("Top processes"), origin: NSPoint(x: 0, y: self.processesHeight-Constants.Popup.separatorHeight), width: self.frame.width) + let container: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: separator.frame.origin.y)) for i in 0...self.numberOfProcesses { - self.processes.append(ProcessView(CGFloat(i))) + let processView = ProcessView(CGFloat(i)) + self.processes.append(processView) + container.addSubview(processView) } - self.processes.forEach{ view.addSubview($0) } + view.addSubview(separator) + view.addSubview(container) - self.addSubview(view) - } - - private func addFirstRow(mView: NSView, y: CGFloat, title: String, value: String) -> NSTextField { - let rowView: NSView = NSView(frame: NSRect(x: 0, y: y, width: mView.frame.width, height: 16)) - - let labelWidth = title.widthOfString(usingFont: .systemFont(ofSize: 10, weight: .light)) + 4 - let labelView: NSTextField = TextView(frame: NSRect(x: 0, y: 1.5, width: labelWidth, height: 13)) - labelView.stringValue = title - labelView.alignment = .natural - labelView.font = NSFont.systemFont(ofSize: 10, weight: .light) - - let valueView: NSTextField = TextView(frame: NSRect(x: labelWidth, y: 1, width: mView.frame.width - labelWidth, height: 14)) - valueView.stringValue = value - valueView.alignment = .right - valueView.font = NSFont.systemFont(ofSize: 11, weight: .medium) - - rowView.addSubview(labelView) - rowView.addSubview(valueView) - mView.addSubview(rowView) - - return valueView + return view } public func loadCallback(_ value: CPU_Load) { @@ -216,7 +207,7 @@ internal class Popup: NSView { public func additionalCallback(_ value: CPU_additional) { DispatchQueue.main.async(execute: { - if value.frequency != nil && (self.frequencyCircle! as NSView).isHidden { + if value.frequency != nil && self.frequencyCircle != nil && (self.frequencyCircle! as NSView).isHidden { (self.frequencyCircle! as NSView).isHidden = false } diff --git a/Modules/Memory/popup.swift b/Modules/Memory/popup.swift index 82f5373d..4c6b6deb 100644 --- a/Modules/Memory/popup.swift +++ b/Modules/Memory/popup.swift @@ -17,9 +17,11 @@ internal class Popup: NSView { private var store: UnsafePointer private var title: String + private var grid: NSGridView? = nil + private let dashboardHeight: CGFloat = 90 - private let chartHeight: CGFloat = 90 - private let detailsHeight: CGFloat = 22*6 + private let chartHeight: CGFloat = 90 + Constants.Popup.separatorHeight + private let detailsHeight: CGFloat = (22*4) + Constants.Popup.separatorHeight private let processHeight: CGFloat = 22 private var totalField: NSTextField? = nil @@ -44,6 +46,11 @@ internal class Popup: NSView { return self.store.pointee.int(key: "\(self.title)_processes", defaultValue: 8) } } + private var processesHeight: CGFloat { + get { + return (self.processHeight*CGFloat(self.numberOfProcesses))+Constants.Popup.separatorHeight + } + } public init(_ title: String, store: UnsafePointer) { self.store = store @@ -53,22 +60,25 @@ internal class Popup: NSView { x: 0, y: 0, width: Constants.Popup.width, - height: dashboardHeight + chartHeight + detailsHeight + (Constants.Popup.separatorHeight*3) + height: dashboardHeight + chartHeight + detailsHeight )) + self.setFrameSize(NSSize(width: self.frame.width, height: self.frame.height+self.processesHeight)) - let h: CGFloat = self.dashboardHeight + self.chartHeight + self.detailsHeight + (self.processHeight*CGFloat(self.numberOfProcesses)) + (Constants.Popup.separatorHeight*3) - self.setFrameSize(NSSize(width: self.frame.width, height: h)) + let gridView: NSGridView = NSGridView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)) + gridView.rowSpacing = 0 + gridView.yPlacement = .fill - self.initDashboard() - self.initChart() - self.initDetails() - self.initProcesses() + gridView.addRow(with: [self.initDashboard()]) + gridView.addRow(with: [self.initChart()]) + gridView.addRow(with: [self.initDetails()]) + gridView.addRow(with: [self.initProcesses()]) - DispatchQueue.main.async(execute: { - if self.frame.size.height != h { - NotificationCenter.default.post(name: .updatePopupSize, object: nil, userInfo: ["module": self.title]) - } - }) + gridView.row(at: 0).height = self.dashboardHeight + gridView.row(at: 1).height = self.chartHeight + gridView.row(at: 2).height = self.detailsHeight + + self.addSubview(gridView) + self.grid = gridView } required init?(coder: NSCoder) { @@ -85,22 +95,23 @@ internal class Popup: NSView { } DispatchQueue.main.async(execute: { - self.subviews.forEach{ $0.removeFromSuperview() } self.processes = [] - let h: CGFloat = self.dashboardHeight + self.chartHeight + self.detailsHeight + (self.processHeight*CGFloat(self.numberOfProcesses)) + (Constants.Popup.separatorHeight*3) + let h: CGFloat = self.dashboardHeight + self.chartHeight + self.detailsHeight + self.processesHeight self.setFrameSize(NSSize(width: self.frame.width, height: h)) - self.initDashboard() - self.initChart() - self.initDetails() - self.initProcesses() - NotificationCenter.default.post(name: .updatePopupSize, object: nil, userInfo: ["module": self.title]) + + self.grid?.setFrameSize(NSSize(width: self.frame.width, height: h)) + + self.grid?.row(at: 3).cell(at: 0).contentView?.removeFromSuperview() + self.grid?.removeRow(at: 3) + self.grid?.addRow(with: [self.initProcesses()]) + self.processesInitialized = false }) } - private func initDashboard() { + private func initDashboard() -> NSView { let view: NSView = NSView(frame: NSRect(x: 0, y: self.frame.height - self.dashboardHeight, width: self.frame.width, height: self.dashboardHeight)) view.wantsLayer = true @@ -117,58 +128,57 @@ internal class Popup: NSView { view.addSubview(self.level!) view.addSubview(container) - self.addSubview(view) + return view } - private func initChart() { - let y: CGFloat = self.frame.height - self.dashboardHeight - Constants.Popup.separatorHeight - let separator = SeparatorView(LocalizedString("Usage history"), origin: NSPoint(x: 0, y: y), width: self.frame.width) - self.addSubview(separator) - - let view: NSView = NSView(frame: NSRect(x: 0, y: y - self.chartHeight, width: self.frame.width, height: self.chartHeight)) - view.wantsLayer = true - view.layer?.backgroundColor = NSColor.lightGray.withAlphaComponent(0.1).cgColor - view.layer?.cornerRadius = 3 + private func initChart() -> NSView { + let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.chartHeight)) + let separator = SeparatorView(LocalizedString("Usage history"), origin: NSPoint(x: 0, y: self.chartHeight-Constants.Popup.separatorHeight), width: self.frame.width) + let container: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: separator.frame.origin.y)) + container.wantsLayer = true + container.layer?.backgroundColor = NSColor.lightGray.withAlphaComponent(0.1).cgColor + container.layer?.cornerRadius = 3 self.chart = LineChartView(frame: NSRect(x: 1, y: 0, width: view.frame.width, height: view.frame.height), num: 120) + container.addSubview(self.chart!) - view.addSubview(self.chart!) + view.addSubview(separator) + view.addSubview(container) - self.addSubview(view) + return view } - private func initDetails() { - let y: CGFloat = self.frame.height - self.dashboardHeight - self.chartHeight - (Constants.Popup.separatorHeight*2) - let separator = SeparatorView(LocalizedString("Details"), origin: NSPoint(x: 0, y: y), width: self.frame.width) - self.addSubview(separator) + private func initDetails() -> NSView { + let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.detailsHeight)) + let separator = SeparatorView(LocalizedString("Details"), origin: NSPoint(x: 0, y: self.detailsHeight-Constants.Popup.separatorHeight), width: self.frame.width) + let container: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: separator.frame.origin.y)) - let view: NSView = NSView(frame: NSRect(x: 0, y: separator.frame.origin.y - self.detailsHeight, width: self.frame.width, height: self.detailsHeight)) + self.activeField = PopupWithColorRow(container, color: NSColor.systemBlue, n: 3, title: "\(LocalizedString("App")):", value: "") + self.wiredField = PopupWithColorRow(container, color: NSColor.systemOrange, n: 2, title: "\(LocalizedString("Wired")):", value: "") + self.compressedField = PopupWithColorRow(container, color: NSColor.systemPink, n: 1, title: "\(LocalizedString("Compressed")):", value: "") + self.freeField = PopupWithColorRow(container, color: NSColor.lightGray.withAlphaComponent(0.5), n: 0, title: "\(LocalizedString("Free")):", value: "") - self.totalField = PopupRow(view, n: 5, title: "\(LocalizedString("Total")):", value: "") - self.usedField = PopupRow(view, n: 4, title: "\(LocalizedString("Used")):", value: "") + view.addSubview(separator) + view.addSubview(container) - self.activeField = PopupWithColorRow(view, color: NSColor.systemBlue, n: 3, title: "\(LocalizedString("App")):", value: "") - self.wiredField = PopupWithColorRow(view, color: NSColor.systemOrange, n: 2, title: "\(LocalizedString("Wired")):", value: "") - self.compressedField = PopupWithColorRow(view, color: NSColor.systemPink, n: 1, title: "\(LocalizedString("Compressed")):", value: "") - self.freeField = PopupWithColorRow(view, color: NSColor.lightGray.withAlphaComponent(0.5), n: 0, title: "\(LocalizedString("Free")):", value: "") - - self.addSubview(view) + return view } - private func initProcesses() { - let height: CGFloat = self.processHeight*CGFloat(self.numberOfProcesses) - let separator = SeparatorView(LocalizedString("Top processes"), origin: NSPoint(x: 0, y: height), width: self.frame.width) - self.addSubview(separator) - - let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: height)) + private func initProcesses() -> NSView { + let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.processesHeight)) + let separator = SeparatorView(LocalizedString("Top processes"), origin: NSPoint(x: 0, y: self.processesHeight-Constants.Popup.separatorHeight), width: self.frame.width) + let container: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: separator.frame.origin.y)) for i in 0...self.numberOfProcesses { - self.processes.append(ProcessView(CGFloat(i))) + let processView = ProcessView(CGFloat(i)) + self.processes.append(processView) + container.addSubview(processView) } - self.processes.forEach{ view.addSubview($0) } + view.addSubview(separator) + view.addSubview(container) - self.addSubview(view) + return view } private func addFirstRow(mView: NSView, y: CGFloat, title: String, value: String) -> NSTextField {