feat: added fixed scale option for Network popup (#1787)

This commit is contained in:
Serhiy Mytrovtsiy
2024-04-29 21:56:12 +02:00
parent a2807a54f7
commit d5d70a299e
3 changed files with 158 additions and 6 deletions

View File

@@ -1487,3 +1487,76 @@ public func restartApp(_ sender: Any, afterDelay seconds: TimeInterval = 0.5) ->
NSApp.terminate(sender)
exit(0)
}
public class StepperInput: NSStackView, NSTextFieldDelegate {
public var callback: ((Int) -> Void) = {_ in }
private let value: NSTextField = NSTextField()
private let stepper: NSStepper = NSStepper()
private let range: NSRange?
public init(_ value: Int, range: NSRange? = nil) {
self.range = range
super.init(frame: .zero)
self.orientation = .horizontal
self.spacing = 2
self.value.font = NSFont.systemFont(ofSize: 12, weight: .regular)
self.value.textColor = .textColor
self.value.isEditable = true
self.value.isSelectable = true
self.value.usesSingleLineMode = true
self.value.maximumNumberOfLines = 1
self.value.focusRingType = .none
self.value.delegate = self
self.value.stringValue = "\(value)"
self.stepper.font = NSFont.systemFont(ofSize: 12, weight: .regular)
self.stepper.doubleValue = Double(value)/100
if let range {
self.stepper.minValue = Double(range.lowerBound)/100
self.stepper.maxValue = Double(range.upperBound)/100
}
self.stepper.increment = 0.01
self.stepper.valueWraps = false
self.stepper.target = self
self.stepper.action = #selector(self.onStepperChange)
self.addArrangedSubview(self.value)
self.addArrangedSubview(self.stepper)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func controlTextDidChange(_ obj: Notification) {
guard let field = obj.object as? NSTextField else { return }
let filtered = field.stringValue.filter{"0123456789".contains($0)}
if filtered != field.stringValue {
field.stringValue = filtered
}
guard var v = Int(field.stringValue) else { return }
if let range = self.range {
if v > range.upperBound {
field.stringValue = "\(range.upperBound)"
v = range.upperBound
} else if v < range.lowerBound {
field.stringValue = "\(range.lowerBound)"
v = range.lowerBound
}
}
self.callback(v)
}
@objc private func onStepperChange(_ sender: NSStepper) {
let value = Int(sender.doubleValue*100)
self.value.stringValue = "\(value)"
self.callback(value)
}
}

View File

@@ -337,3 +337,44 @@ public var LineChartHistory: [KeyValue_p] = [
KeyValue_t(key: "300", value: "5 minutes"),
KeyValue_t(key: "600", value: "10 minutes")
]
public struct SizeUnit: KeyValue_p, Equatable {
public let key: String
public let value: String
public var additional: Any?
public static func == (lhs: SizeUnit, rhs: SizeUnit) -> Bool {
return lhs.key == rhs.key
}
}
extension SizeUnit: CaseIterable {
public static var byte: SizeUnit { return SizeUnit(key: "byte", value: "Bytes") }
public static var KB: SizeUnit { return SizeUnit(key: "KB", value: "KB") }
public static var MB: SizeUnit { return SizeUnit(key: "MB", value: "MB") }
public static var GB: SizeUnit { return SizeUnit(key: "GB", value: "GB") }
public static var TB: SizeUnit { return SizeUnit(key: "TB", value: "TB") }
public static var allCases: [SizeUnit] {
[.byte, .KB, .MB, .GB, .TB]
}
public static func fromString(_ key: String, defaultValue: SizeUnit = .byte) -> SizeUnit {
return SizeUnit.allCases.first{ $0.key == key } ?? defaultValue
}
public func toBytes(_ value: Int) -> Int {
switch self {
case .KB:
return value * 1_024
case .MB:
return value * 1_024 * 1_024
case .GB:
return value * 1_024 * 1_024 * 1_024
case .TB:
return value * 1_024 * 1_024 * 1_024 * 1_024
default:
return value
}
}
}

View File

@@ -58,6 +58,9 @@ internal class Popup: PopupWrapper {
private var chart: NetworkChartView? = nil
private var reverseOrderState: Bool = false
private var chartScale: Scale = .none
private var chartFixedScale: Int = 12
private var chartFixedScaleSize: SizeUnit = .MB
private var chartPrefSection: PreferencesSection? = nil
private var connectivityChart: GridChartView? = nil
private var processes: ProcessesView? = nil
private var sliderView: NSView? = nil
@@ -108,6 +111,8 @@ internal class Popup: PopupWrapper {
self.uploadColorState = Color.fromString(Store.shared.string(key: "\(self.title)_uploadColor", defaultValue: self.uploadColorState.key))
self.reverseOrderState = Store.shared.bool(key: "\(self.title)_reverseOrder", defaultValue: self.reverseOrderState)
self.chartScale = Scale.fromString(Store.shared.string(key: "\(self.title)_chartScale", defaultValue: self.chartScale.key))
self.chartFixedScale = Store.shared.int(key: "\(self.title)_chartFixedScale", defaultValue: self.chartFixedScale)
self.chartFixedScaleSize = SizeUnit.fromString(Store.shared.string(key: "\(self.title)_chartFixedScaleSize", defaultValue: self.chartFixedScaleSize.key))
self.publicIPState = Store.shared.bool(key: "\(self.title)_publicIP", defaultValue: self.publicIPState)
self.spacing = 0
@@ -183,7 +188,9 @@ internal class Popup: PopupWrapper {
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
num: 120, reversedOrder: self.reverseOrderState, outColor: self.uploadColor, inColor: self.downloadColor,
scale: self.chartScale,
fixedScale: Double(self.chartFixedScaleSize.toBytes(self.chartFixedScale))
)
chart.base = self.base
container.addSubview(chart)
@@ -523,13 +530,31 @@ internal class Popup: PopupWrapper {
))
]))
view.addArrangedSubview(PreferencesSection([
self.chartPrefSection = PreferencesSection([
PreferencesRow(localizedString("Main chart scaling"), component: selectView(
action: #selector(self.toggleChartScale),
items: Scale.allCases.filter({ $0 != .fixed }),
items: Scale.allCases,
selected: self.chartScale.key
))
]))
)),
PreferencesRow(localizedString("Scale value"), component: {
let view: NSStackView = NSStackView()
view.orientation = .horizontal
view.spacing = 2
let valueField = StepperInput(self.chartFixedScale, range: NSRange(location: 1, length: 1023))
valueField.callback = self.toggleFixedScale
valueField.widthAnchor.constraint(equalToConstant: 80).isActive = true
view.addArrangedSubview(NSView())
view.addArrangedSubview(valueField)
view.addArrangedSubview(selectView(
action: #selector(self.toggleUploadScaleSize),
items: SizeUnit.allCases,
selected: self.chartFixedScaleSize.key
))
return view
}())
])
view.addArrangedSubview(self.chartPrefSection!)
self.chartPrefSection?.toggleVisibility(1, newState: self.chartScale == .fixed)
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Public IP"), component: switchView(
@@ -579,7 +604,8 @@ internal class Popup: PopupWrapper {
guard let key = sender.representedObject as? String,
let value = Scale.allCases.first(where: { $0.key == key }) else { return }
self.chartScale = value
self.chart?.setScale(self.chartScale)
self.chart?.setScale(self.chartScale, Double(self.chartFixedScaleSize.toBytes(self.chartFixedScale)))
self.chartPrefSection?.toggleVisibility(1, newState: self.chartScale == .fixed)
Store.shared.set(key: "\(self.title)_chartScale", value: key)
self.display()
}
@@ -596,6 +622,18 @@ internal class Popup: PopupWrapper {
self.recalculateHeight()
})
}
@objc private func toggleFixedScale(_ newValue: Int) {
self.chart?.setScale(self.chartScale, Double(self.chartFixedScaleSize.toBytes(newValue)))
Store.shared.set(key: "\(self.title)_chartFixedScale", value: newValue)
}
@objc private func toggleUploadScaleSize(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String,
let value = SizeUnit.allCases.first(where: { $0.key == key }) else { return }
self.chartFixedScaleSize = value
self.chart?.setScale(self.chartScale, Double(self.chartFixedScaleSize.toBytes(self.chartFixedScale)))
Store.shared.set(key: "\(self.title)_chartFixedScaleSize", value: key)
self.display()
}
// MARK: - helpers