mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
feat: moved network chart to the network chart widget. Replaced NetworkChart with NetworkChartV2.
This commit is contained in:
@@ -19,10 +19,10 @@ public class NetworkChart: WidgetWrapper {
|
||||
private var downloadColor: Color = .secondBlue
|
||||
private var uploadColor: Color = .secondRed
|
||||
private var scaleState: Scale = .linear
|
||||
private var commonScaleState: Bool = true
|
||||
private var reverseOrderState: Bool = false
|
||||
|
||||
private var chart: NetworkChartView = NetworkChartView(frame: NSRect(x: 0, y: 0, width: 30, height: Constants.Widget.height-(2*Constants.Widget.margin.y)), num: 60)
|
||||
private var points: [(Double, Double)] = Array(repeating: (0, 0), count: 60)
|
||||
|
||||
private var width: CGFloat {
|
||||
get {
|
||||
switch self.historyCount {
|
||||
@@ -81,16 +81,7 @@ public class NetworkChart: WidgetWrapper {
|
||||
self.downloadColor = Color.fromString(Store.shared.string(key: "\(self.title)_\(self.type.rawValue)_downloadColor", defaultValue: self.downloadColor.key))
|
||||
self.uploadColor = Color.fromString(Store.shared.string(key: "\(self.title)_\(self.type.rawValue)_uploadColor", defaultValue: self.uploadColor.key))
|
||||
self.scaleState = Scale.fromString(Store.shared.string(key: "\(self.title)_\(self.type.rawValue)_scale", defaultValue: self.scaleState.key))
|
||||
self.commonScaleState = Store.shared.bool(key: "\(self.title)_\(self.type.rawValue)_commonScale", defaultValue: self.commonScaleState)
|
||||
self.reverseOrderState = Store.shared.bool(key: "\(self.title)_\(self.type.rawValue)_reverseOrder", defaultValue: self.reverseOrderState)
|
||||
|
||||
if let downloadColor = self.downloadColor.additional as? NSColor,
|
||||
let uploadColor = self.uploadColor.additional as? NSColor {
|
||||
self.chart.setColors(in: downloadColor, out: uploadColor)
|
||||
}
|
||||
self.chart.setScale(self.scaleState, self.commonScaleState)
|
||||
self.chart.reinit(self.historyCount)
|
||||
self.chart.setReverseOrder(self.reverseOrderState)
|
||||
}
|
||||
|
||||
if preview {
|
||||
@@ -98,7 +89,7 @@ public class NetworkChart: WidgetWrapper {
|
||||
for _ in 0..<60 {
|
||||
list.append((Double.random(in: 0..<23), Double.random(in: 0..<23)))
|
||||
}
|
||||
self.chart.points = list
|
||||
self.points = list
|
||||
}
|
||||
|
||||
let style = NSMutableParagraphStyle()
|
||||
@@ -166,9 +157,74 @@ public class NetworkChart: WidgetWrapper {
|
||||
width: box.bounds.width - (offset*2+lineWidth),
|
||||
height: box.bounds.height - offset
|
||||
)
|
||||
self.chart.setFrameSize(NSSize(width: chartFrame.width, height: chartFrame.height))
|
||||
self.chart.setFrameOrigin(NSPoint(x: chartFrame.origin.x, y: chartFrame.origin.y))
|
||||
self.chart.draw(chartFrame)
|
||||
let points = self.points
|
||||
var topMax: Double = (self.reverseOrderState ? points.map{ $0.0 }.max() : points.map{ $0.1 }.max()) ?? 0
|
||||
var bottomMax: Double = (self.reverseOrderState ? points.map{ $0.1 }.max() : points.map{ $0.0 }.max()) ?? 0
|
||||
if topMax == 0 {
|
||||
topMax = 1
|
||||
}
|
||||
if bottomMax == 0 {
|
||||
bottomMax = 1
|
||||
}
|
||||
|
||||
let zero: CGFloat = (chartFrame.height/2) + chartFrame.origin.y
|
||||
let xRatio: CGFloat = (chartFrame.width + (lineWidth*3)) / CGFloat(points.count)
|
||||
let xCenter: CGFloat = chartFrame.height/2 + chartFrame.origin.y
|
||||
|
||||
let columnXPoint = { (point: Int) -> CGFloat in
|
||||
return (CGFloat(point) * xRatio) + (chartFrame.origin.x - lineWidth)
|
||||
}
|
||||
|
||||
let topYPoint = { (point: Int) -> CGFloat in
|
||||
let value = self.reverseOrderState ? points[point].0 : points[point].1
|
||||
return scaleValue(scale: self.scaleState, value: value, maxValue: topMax, maxHeight: chartFrame.height/2, limit: 1) + xCenter
|
||||
}
|
||||
let bottomYPoint = { (point: Int) -> CGFloat in
|
||||
let value = self.reverseOrderState ? points[point].1 : points[point].0
|
||||
return xCenter - scaleValue(scale: self.scaleState, value: value, maxValue: bottomMax, maxHeight: chartFrame.height/2, limit: 1)
|
||||
}
|
||||
|
||||
let topLinePath = NSBezierPath()
|
||||
topLinePath.move(to: CGPoint(x: columnXPoint(0), y: topYPoint(0)))
|
||||
let bottomLinePath = NSBezierPath()
|
||||
bottomLinePath.move(to: CGPoint(x: columnXPoint(0), y: bottomYPoint(0)))
|
||||
|
||||
for i in 1..<points.count {
|
||||
topLinePath.line(to: CGPoint(x: columnXPoint(i), y: topYPoint(i)))
|
||||
bottomLinePath.line(to: CGPoint(x: columnXPoint(i), y: bottomYPoint(i)))
|
||||
}
|
||||
|
||||
let topColor = (self.reverseOrderState ? self.uploadColor : self.downloadColor).additional as? NSColor
|
||||
let bottomColor = (self.reverseOrderState ? self.downloadColor : self.uploadColor).additional as? NSColor
|
||||
|
||||
bottomColor?.setStroke()
|
||||
topLinePath.lineWidth = lineWidth
|
||||
topLinePath.stroke()
|
||||
|
||||
topColor?.setStroke()
|
||||
bottomLinePath.lineWidth = lineWidth
|
||||
bottomLinePath.stroke()
|
||||
|
||||
context.saveGState()
|
||||
|
||||
var underLinePath = topLinePath.copy() as! NSBezierPath
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(points.count), y: zero))
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(0), y: zero))
|
||||
underLinePath.close()
|
||||
underLinePath.addClip()
|
||||
bottomColor?.withAlphaComponent(0.5).setFill()
|
||||
NSBezierPath(rect: self.frame).fill()
|
||||
|
||||
context.restoreGState()
|
||||
context.saveGState()
|
||||
|
||||
underLinePath = bottomLinePath.copy() as! NSBezierPath
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(points.count), y: zero))
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(0), y: zero))
|
||||
underLinePath.close()
|
||||
underLinePath.addClip()
|
||||
topColor?.withAlphaComponent(0.5).setFill()
|
||||
NSBezierPath(rect: self.frame).fill()
|
||||
|
||||
context.restoreGState()
|
||||
|
||||
@@ -182,9 +238,13 @@ public class NetworkChart: WidgetWrapper {
|
||||
}
|
||||
|
||||
public func setValue(upload: Double, download: Double) {
|
||||
self.points.remove(at: 0)
|
||||
self.points.append((upload, download))
|
||||
|
||||
DispatchQueue.main.async(execute: {
|
||||
self.chart.addValue(upload: upload, download: download)
|
||||
self.display()
|
||||
if self.window?.isVisible ?? false {
|
||||
self.display()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -241,12 +301,6 @@ public class NetworkChart: WidgetWrapper {
|
||||
selected: self.scaleState.key
|
||||
))
|
||||
|
||||
view.addArrangedSubview(toggleSettingRow(
|
||||
title: localizedString("Common scale"),
|
||||
action: #selector(toggleCommonScale),
|
||||
state: self.commonScaleState
|
||||
))
|
||||
|
||||
view.addArrangedSubview(toggleSettingRow(
|
||||
title: localizedString("Reverse order"),
|
||||
action: #selector(toggleReverseOrder),
|
||||
@@ -289,11 +343,18 @@ public class NetworkChart: WidgetWrapper {
|
||||
}
|
||||
|
||||
@objc private func toggleHistoryCount(_ sender: NSMenuItem) {
|
||||
guard let key = sender.representedObject as? String, let value = Int(key) else { return }
|
||||
self.historyCount = value
|
||||
guard let key = sender.representedObject as? String, let num = Int(key) else { return }
|
||||
self.historyCount = num
|
||||
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_historyCount", value: self.historyCount)
|
||||
|
||||
if num < self.points.count {
|
||||
self.points = Array(self.points[self.points.count-num..<self.points.count])
|
||||
} else {
|
||||
let origin = self.points
|
||||
self.points = Array(repeating: (0, 0), count: num)
|
||||
self.points.replaceSubrange(Range(uncheckedBounds: (lower: origin.count, upper: num)), with: origin)
|
||||
}
|
||||
|
||||
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_historyCount", value: value)
|
||||
self.chart.reinit(value)
|
||||
self.display()
|
||||
}
|
||||
|
||||
@@ -303,10 +364,6 @@ public class NetworkChart: WidgetWrapper {
|
||||
self.downloadColor = newColor
|
||||
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_downloadColor", value: newColor.key)
|
||||
}
|
||||
|
||||
if let downloadColor = self.downloadColor.additional as? NSColor {
|
||||
self.chart.setColors(in: downloadColor)
|
||||
}
|
||||
self.display()
|
||||
}
|
||||
|
||||
@@ -316,10 +373,6 @@ public class NetworkChart: WidgetWrapper {
|
||||
self.uploadColor = newColor
|
||||
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_uploadColor", value: newColor.key)
|
||||
}
|
||||
|
||||
if let uploadColor = self.uploadColor.additional as? NSColor {
|
||||
self.chart.setColors(out: uploadColor)
|
||||
}
|
||||
self.display()
|
||||
}
|
||||
|
||||
@@ -327,21 +380,12 @@ public class NetworkChart: WidgetWrapper {
|
||||
guard let key = sender.representedObject as? String,
|
||||
let value = Scale.allCases.first(where: { $0.key == key }) else { return }
|
||||
self.scaleState = value
|
||||
self.chart.setScale(value, self.commonScaleState)
|
||||
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_scale", value: key)
|
||||
self.display()
|
||||
}
|
||||
|
||||
@objc private func toggleCommonScale(_ sender: NSControl) {
|
||||
self.commonScaleState = controlState(sender)
|
||||
self.chart.setScale(self.scaleState, self.commonScaleState)
|
||||
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_commonScale", value: self.commonScaleState)
|
||||
self.display()
|
||||
}
|
||||
|
||||
@objc private func toggleReverseOrder(_ sender: NSControl) {
|
||||
self.reverseOrderState = controlState(sender)
|
||||
self.chart.setReverseOrder(self.reverseOrderState)
|
||||
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_reverseOrder", value: self.reverseOrderState)
|
||||
self.display()
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public class LineChartView: NSView {
|
||||
private var cursor: NSPoint? = nil
|
||||
private var stop: Bool = false
|
||||
|
||||
public init(frame: NSRect, num: Int, suffix: String = "", color: NSColor = .controlAccentColor, scale: Scale = .none, fixedScale: Double = 1) {
|
||||
public init(frame: NSRect, num: Int, suffix: String = "%", color: NSColor = .controlAccentColor, scale: Scale = .none, fixedScale: Double = 1) {
|
||||
self.points = Array(repeating: nil, count: num)
|
||||
self.suffix = suffix
|
||||
self.color = color
|
||||
@@ -198,7 +198,7 @@ public class LineChartView: NSView {
|
||||
}
|
||||
|
||||
let point = CGPoint(
|
||||
x: (CGFloat(i) * xRatio) + dirtyRect.origin.x,
|
||||
x: (CGFloat(i) * xRatio),
|
||||
y: y
|
||||
)
|
||||
line.append(point)
|
||||
@@ -380,7 +380,7 @@ public class LineChartView: NSView {
|
||||
}
|
||||
}
|
||||
|
||||
public class NetworkChartViewV2: NSView {
|
||||
public class NetworkChartView: NSView {
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var base: DataSizeBase = .byte
|
||||
@@ -465,174 +465,6 @@ public class NetworkChartViewV2: NSView {
|
||||
}
|
||||
}
|
||||
|
||||
public class NetworkChartView: NSView {
|
||||
public var id: String = UUID().uuidString
|
||||
public var base: DataSizeBase = .byte
|
||||
public var topColor: NSColor
|
||||
public var bottomColor: NSColor
|
||||
public var points: [(Double, Double)]
|
||||
|
||||
private var scale: Scale = .none
|
||||
private var fixedScale: Double
|
||||
private var commonScale: Bool = true
|
||||
private var reverseOrder: Bool = false
|
||||
|
||||
public init(frame: NSRect, num: Int, outColor: NSColor = .systemRed, inColor: NSColor = .systemBlue, scale: Scale = .none, fixedScale: Double = 1) {
|
||||
self.points = Array(repeating: (0, 0), count: num)
|
||||
self.topColor = inColor
|
||||
self.bottomColor = outColor
|
||||
self.scale = scale
|
||||
self.fixedScale = fixedScale
|
||||
super.init(frame: frame)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public override func draw(_ dirtyRect: NSRect) {
|
||||
super.draw(dirtyRect)
|
||||
|
||||
guard let context = NSGraphicsContext.current?.cgContext else { return }
|
||||
context.setShouldAntialias(true)
|
||||
|
||||
let points = self.points
|
||||
var topMax: Double = (self.reverseOrder ? points.map{ $0.1 }.max() : points.map{ $0.0 }.max()) ?? 0
|
||||
var bottomMax: Double = (self.reverseOrder ? points.map{ $0.0 }.max() : points.map{ $0.1 }.max()) ?? 0
|
||||
if topMax == 0 {
|
||||
topMax = 1
|
||||
}
|
||||
if bottomMax == 0 {
|
||||
bottomMax = 1
|
||||
}
|
||||
|
||||
if !self.commonScale {
|
||||
if bottomMax > topMax {
|
||||
topMax = bottomMax
|
||||
} else {
|
||||
bottomMax = topMax
|
||||
}
|
||||
}
|
||||
|
||||
let lineWidth = 1 / (NSScreen.main?.backingScaleFactor ?? 1)
|
||||
let zero: CGFloat = (self.frame.height/2) + self.frame.origin.y
|
||||
let xRatio: CGFloat = (self.frame.width + (lineWidth*3)) / CGFloat(points.count)
|
||||
let xCenter: CGFloat = self.frame.height/2 + self.frame.origin.y
|
||||
|
||||
let columnXPoint = { (point: Int) -> CGFloat in
|
||||
return (CGFloat(point) * xRatio) + (self.frame.origin.x - lineWidth)
|
||||
}
|
||||
|
||||
let topYPoint = { (point: Int) -> CGFloat in
|
||||
let value = self.reverseOrder ? points[point].1 : points[point].0
|
||||
return scaleValue(scale: self.scale, value: value, maxValue: topMax, maxHeight: self.frame.height/2, limit: self.fixedScale) + xCenter
|
||||
}
|
||||
let bottomYPoint = { (point: Int) -> CGFloat in
|
||||
let value = self.reverseOrder ? points[point].0 : points[point].1
|
||||
return xCenter - scaleValue(scale: self.scale, value: value, maxValue: bottomMax, maxHeight: self.frame.height/2, limit: self.fixedScale)
|
||||
}
|
||||
|
||||
let topLinePath = NSBezierPath()
|
||||
topLinePath.move(to: CGPoint(x: columnXPoint(0), y: topYPoint(0)))
|
||||
|
||||
let bottomLinePath = NSBezierPath()
|
||||
bottomLinePath.move(to: CGPoint(x: columnXPoint(0), y: bottomYPoint(0)))
|
||||
|
||||
for i in 1..<points.count {
|
||||
topLinePath.line(to: CGPoint(x: columnXPoint(i), y: topYPoint(i)))
|
||||
bottomLinePath.line(to: CGPoint(x: columnXPoint(i), y: bottomYPoint(i)))
|
||||
}
|
||||
|
||||
let topColor = self.reverseOrder ? self.bottomColor : self.topColor
|
||||
let bottomColor = self.reverseOrder ? self.topColor : self.bottomColor
|
||||
|
||||
bottomColor.setStroke()
|
||||
topLinePath.lineWidth = lineWidth
|
||||
topLinePath.stroke()
|
||||
|
||||
topColor.setStroke()
|
||||
bottomLinePath.lineWidth = lineWidth
|
||||
bottomLinePath.stroke()
|
||||
|
||||
context.saveGState()
|
||||
|
||||
var underLinePath = topLinePath.copy() as! NSBezierPath
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(points.count), y: zero))
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(0), y: zero))
|
||||
underLinePath.close()
|
||||
underLinePath.addClip()
|
||||
bottomColor.withAlphaComponent(0.5).setFill()
|
||||
NSBezierPath(rect: self.frame).fill()
|
||||
|
||||
context.restoreGState()
|
||||
context.saveGState()
|
||||
|
||||
underLinePath = bottomLinePath.copy() as! NSBezierPath
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(points.count), y: zero))
|
||||
underLinePath.line(to: CGPoint(x: columnXPoint(0), y: zero))
|
||||
underLinePath.close()
|
||||
underLinePath.addClip()
|
||||
topColor.withAlphaComponent(0.5).setFill()
|
||||
NSBezierPath(rect: self.frame).fill()
|
||||
}
|
||||
|
||||
public func addValue(upload: Double, download: Double) {
|
||||
self.points.remove(at: 0)
|
||||
self.points.append((upload, download))
|
||||
|
||||
if self.window?.isVisible ?? false {
|
||||
self.display()
|
||||
}
|
||||
}
|
||||
|
||||
public func reinit(_ num: Int = 60) {
|
||||
guard self.points.count != num else { return }
|
||||
|
||||
if num < self.points.count {
|
||||
self.points = Array(self.points[self.points.count-num..<self.points.count])
|
||||
} else {
|
||||
let origin = self.points
|
||||
self.points = Array(repeating: (0, 0), count: num)
|
||||
self.points.replaceSubrange(Range(uncheckedBounds: (lower: origin.count, upper: num)), with: origin)
|
||||
}
|
||||
}
|
||||
|
||||
public func setScale(_ newScale: Scale, _ commonScale: Bool = false, _ fixedScale: Double = 1) {
|
||||
self.scale = newScale
|
||||
self.fixedScale = fixedScale
|
||||
self.commonScale = commonScale
|
||||
|
||||
if self.window?.isVisible ?? false {
|
||||
self.display()
|
||||
}
|
||||
}
|
||||
|
||||
public func setReverseOrder(_ newValue: Bool) {
|
||||
self.reverseOrder = newValue
|
||||
|
||||
if self.window?.isVisible ?? false {
|
||||
self.display()
|
||||
}
|
||||
}
|
||||
|
||||
public func setColors(in inColor: NSColor? = nil, out outColor: NSColor? = nil) {
|
||||
var needUpdate: Bool = false
|
||||
|
||||
if let newColor = inColor, self.topColor != newColor {
|
||||
self.topColor = newColor
|
||||
needUpdate = true
|
||||
}
|
||||
if let newColor = outColor, self.bottomColor != newColor {
|
||||
self.bottomColor = newColor
|
||||
needUpdate = true
|
||||
}
|
||||
|
||||
if needUpdate && self.window?.isVisible ?? false {
|
||||
self.display()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PieChartView: NSView {
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
|
||||
@@ -420,7 +420,7 @@ internal class NameView: NSStackView {
|
||||
}
|
||||
|
||||
internal class ChartView: NSStackView {
|
||||
private var chart: NetworkChartViewV2? = nil
|
||||
private var chart: NetworkChartView? = nil
|
||||
private var ready: Bool = false
|
||||
|
||||
private var readColor: NSColor {
|
||||
@@ -436,7 +436,7 @@ internal class ChartView: NSStackView {
|
||||
self.wantsLayer = true
|
||||
self.layer?.cornerRadius = 3
|
||||
|
||||
let chart = NetworkChartViewV2(frame: NSRect(
|
||||
let chart = NetworkChartView(frame: NSRect(
|
||||
x: 0,
|
||||
y: 1,
|
||||
width: self.frame.width,
|
||||
|
||||
@@ -14,7 +14,7 @@ import Kit
|
||||
|
||||
public class Portal: PortalWrapper {
|
||||
private var circle: PieChartView? = nil
|
||||
private var chart: NetworkChartViewV2? = nil
|
||||
private var chart: NetworkChartView? = nil
|
||||
|
||||
private var nameField: NSTextField? = nil
|
||||
private var usedField: NSTextField? = nil
|
||||
@@ -91,7 +91,7 @@ public class Portal: PortalWrapper {
|
||||
self.usedField = portalRow(view, title: "\(localizedString("Used")):")
|
||||
self.freeField = portalRow(view, title: "\(localizedString("Free")):")
|
||||
|
||||
let chart = NetworkChartViewV2(frame: NSRect.zero, num: 120, minMax: false, outColor: self.writeColor, inColor: self.readColor)
|
||||
let chart = NetworkChartView(frame: NSRect.zero, num: 120, minMax: false, outColor: self.writeColor, inColor: self.readColor)
|
||||
chart.heightAnchor.constraint(equalToConstant: 26).isActive = true
|
||||
self.chart = chart
|
||||
view.addArrangedSubview(chart)
|
||||
|
||||
@@ -55,7 +55,8 @@ internal class Popup: PopupWrapper {
|
||||
private var processesInitialized: Bool = false
|
||||
private var connectionInitialized: Bool = false
|
||||
|
||||
private var chart: NetworkChartViewV2? = nil
|
||||
private var chart: NetworkChartView? = nil
|
||||
private var reverseOrderState: Bool = false
|
||||
private var chartScale: Scale = .none
|
||||
private var connectivityChart: GridChartView? = nil
|
||||
private var processes: ProcessesView? = nil
|
||||
@@ -89,7 +90,6 @@ internal class Popup: PopupWrapper {
|
||||
}
|
||||
return value
|
||||
}
|
||||
private var reverseOrderState: Bool = false
|
||||
|
||||
private var latency: [Double] = []
|
||||
|
||||
@@ -175,7 +175,7 @@ internal class Popup: PopupWrapper {
|
||||
container.layer?.backgroundColor = NSColor.lightGray.withAlphaComponent(0.1).cgColor
|
||||
container.layer?.cornerRadius = 3
|
||||
|
||||
let chart = NetworkChartViewV2(
|
||||
let chart = NetworkChartView(
|
||||
frame: NSRect(x: 0, y: 1, width: container.frame.width, height: container.frame.height - 2),
|
||||
num: 120, reversedOrder: self.reverseOrderState, outColor: self.uploadColor, inColor: self.downloadColor, scale: self.chartScale
|
||||
)
|
||||
|
||||
@@ -13,26 +13,32 @@ import Cocoa
|
||||
import Kit
|
||||
|
||||
public class Portal: PortalWrapper {
|
||||
private var chart: NetworkChartViewV2? = nil
|
||||
private var chart: NetworkChartView? = nil
|
||||
|
||||
private var publicIPField: NSTextField? = nil
|
||||
|
||||
private var base: DataSizeBase {
|
||||
DataSizeBase(rawValue: Store.shared.string(key: "\(self.name)_base", defaultValue: "byte")) ?? .byte
|
||||
}
|
||||
private var reverseOrderState: Bool {
|
||||
Store.shared.bool(key: "\(self.name)_reverseOrder", defaultValue: false)
|
||||
}
|
||||
private var chartScale: Scale {
|
||||
Scale.fromString(Store.shared.string(key: "\(self.name)_chartScale", defaultValue: Scale.none.key))
|
||||
}
|
||||
|
||||
private var downloadColorState: Color = .secondBlue
|
||||
private var downloadColor: NSColor {
|
||||
let v = Color.fromString(Store.shared.string(key: "\(self.name)_downloadColor", defaultValue: Color.secondBlue.key))
|
||||
var value = NSColor.systemBlue
|
||||
if let color = self.downloadColorState.additional as? NSColor {
|
||||
if let color = v.additional as? NSColor {
|
||||
value = color
|
||||
}
|
||||
return value
|
||||
}
|
||||
private var uploadColorState: Color = .secondRed
|
||||
private var uploadColor: NSColor {
|
||||
let v = Color.fromString(Store.shared.string(key: "\(self.name)_uploadColor", defaultValue: Color.secondRed.key))
|
||||
var value = NSColor.systemRed
|
||||
if let color = self.uploadColorState.additional as? NSColor {
|
||||
if let color = v.additional as? NSColor {
|
||||
value = color
|
||||
}
|
||||
return value
|
||||
@@ -41,11 +47,9 @@ public class Portal: PortalWrapper {
|
||||
private var initialized: Bool = false
|
||||
|
||||
public override func load() {
|
||||
self.loadColors()
|
||||
|
||||
let view = NSStackView()
|
||||
view.orientation = .vertical
|
||||
view.distribution = .fillEqually
|
||||
view.distribution = .fill
|
||||
view.spacing = Constants.Popup.spacing*2
|
||||
view.edgeInsets = NSEdgeInsets(
|
||||
top: 0,
|
||||
@@ -54,8 +58,16 @@ public class Portal: PortalWrapper {
|
||||
right: Constants.Popup.spacing*2
|
||||
)
|
||||
|
||||
let chartView = self.chartView()
|
||||
view.addArrangedSubview(chartView)
|
||||
let chart = NetworkChartView(
|
||||
frame: CGRect(x: 0, y: 0, width: self.frame.width - (Constants.Popup.spacing*8), height: 68),
|
||||
num: 120,
|
||||
reversedOrder: self.reverseOrderState,
|
||||
outColor: self.uploadColor,
|
||||
inColor: self.downloadColor,
|
||||
scale: self.chartScale
|
||||
)
|
||||
self.chart = chart
|
||||
view.addArrangedSubview(chart)
|
||||
|
||||
self.publicIPField = portalRow(view, title: "\(localizedString("Public IP")):", value: localizedString("Unknown"))
|
||||
view.subviews.last?.heightAnchor.constraint(equalToConstant: 16).isActive = true
|
||||
@@ -63,24 +75,6 @@ public class Portal: PortalWrapper {
|
||||
self.addArrangedSubview(view)
|
||||
}
|
||||
|
||||
public func loadColors() {
|
||||
self.downloadColorState = Color.fromString(Store.shared.string(key: "\(self.name)_downloadColor", defaultValue: self.downloadColorState.key))
|
||||
self.uploadColorState = Color.fromString(Store.shared.string(key: "\(self.name)_uploadColor", defaultValue: self.uploadColorState.key))
|
||||
}
|
||||
|
||||
private func chartView() -> NSView {
|
||||
let view = NSStackView()
|
||||
view.orientation = .vertical
|
||||
view.distribution = .fill
|
||||
view.spacing = Constants.Popup.spacing*2
|
||||
let chart = NetworkChartViewV2(frame: NSRect.zero, num: 120, outColor: self.uploadColor, inColor: self.downloadColor)
|
||||
self.chart = chart
|
||||
|
||||
view.addArrangedSubview(chart)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
public func usageCallback(_ value: Network_Usage) {
|
||||
DispatchQueue.main.async(execute: {
|
||||
if let chart = self.chart {
|
||||
@@ -88,6 +82,8 @@ public class Portal: PortalWrapper {
|
||||
chart.base = self.base
|
||||
}
|
||||
chart.addValue(upload: Double(value.bandwidth.upload), download: Double(value.bandwidth.download))
|
||||
chart.setScale(self.chartScale, 1)
|
||||
chart.setColors(in: self.downloadColor, out: self.uploadColor)
|
||||
}
|
||||
|
||||
if let view = self.publicIPField, view.stringValue != value.raddr.v4 {
|
||||
|
||||
@@ -149,7 +149,7 @@ class SettingsWindow: NSWindow, NSWindowDelegate, NSToolbarDelegate {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
|
||||
return [.flexibleSpace, .toggleButton]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user