Skip to content

Commit

Permalink
feat: added fixed scale option for Network popup (#1787)
Browse files Browse the repository at this point in the history
  • Loading branch information
exelban committed Apr 29, 2024
1 parent a2807a5 commit d5d70a2
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 6 deletions.
73 changes: 73 additions & 0 deletions Kit/helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
41 changes: 41 additions & 0 deletions Kit/types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
50 changes: 44 additions & 6 deletions Modules/Net/popup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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()
}
Expand All @@ -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

Expand Down

0 comments on commit d5d70a2

Please sign in to comment.