2019-01-02 19:46:27 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2021-06-17 14:56:46 +00:00
|
|
|
// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved.
|
2019-01-02 19:46:27 +00:00
|
|
|
|
|
|
|
import Cocoa
|
|
|
|
|
2019-01-06 13:21:06 +00:00
|
|
|
class EditableKeyValueRow: NSView {
|
2019-01-02 19:46:27 +00:00
|
|
|
let keyLabel: NSTextField = {
|
|
|
|
let keyLabel = NSTextField()
|
|
|
|
keyLabel.isEditable = false
|
|
|
|
keyLabel.isSelectable = false
|
|
|
|
keyLabel.isBordered = false
|
|
|
|
keyLabel.alignment = .right
|
|
|
|
keyLabel.maximumNumberOfLines = 1
|
|
|
|
keyLabel.lineBreakMode = .byTruncatingTail
|
|
|
|
keyLabel.backgroundColor = .clear
|
|
|
|
return keyLabel
|
|
|
|
}()
|
|
|
|
|
|
|
|
let valueLabel: NSTextField = {
|
|
|
|
let valueLabel = NSTextField()
|
|
|
|
valueLabel.isSelectable = true
|
|
|
|
valueLabel.maximumNumberOfLines = 1
|
|
|
|
valueLabel.lineBreakMode = .byTruncatingTail
|
|
|
|
return valueLabel
|
|
|
|
}()
|
|
|
|
|
2019-03-16 13:58:54 +00:00
|
|
|
let valueImageView: NSImageView?
|
|
|
|
|
2019-01-02 19:46:27 +00:00
|
|
|
var key: String {
|
|
|
|
get { return keyLabel.stringValue }
|
|
|
|
set(value) { keyLabel.stringValue = value }
|
|
|
|
}
|
|
|
|
var value: String {
|
|
|
|
get { return valueLabel.stringValue }
|
|
|
|
set(value) { valueLabel.stringValue = value }
|
|
|
|
}
|
|
|
|
var isKeyInBold: Bool {
|
|
|
|
get { return keyLabel.font == NSFont.boldSystemFont(ofSize: 0) }
|
|
|
|
set(value) {
|
|
|
|
if value {
|
|
|
|
keyLabel.font = NSFont.boldSystemFont(ofSize: 0)
|
|
|
|
} else {
|
|
|
|
keyLabel.font = NSFont.systemFont(ofSize: 0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-16 13:58:54 +00:00
|
|
|
var valueImage: NSImage? {
|
|
|
|
get { return valueImageView?.image }
|
|
|
|
set(value) { valueImageView?.image = value }
|
|
|
|
}
|
|
|
|
|
2021-07-29 10:27:04 +00:00
|
|
|
var statusObservationToken: AnyObject?
|
|
|
|
var isOnDemandEnabledObservationToken: AnyObject?
|
|
|
|
var hasOnDemandRulesObservationToken: AnyObject?
|
2019-01-02 19:46:27 +00:00
|
|
|
|
2019-01-06 13:21:06 +00:00
|
|
|
override var intrinsicContentSize: NSSize {
|
|
|
|
let height = max(keyLabel.intrinsicContentSize.height, valueLabel.intrinsicContentSize.height)
|
|
|
|
return NSSize(width: NSView.noIntrinsicMetric, height: height)
|
|
|
|
}
|
|
|
|
|
2019-03-16 13:58:54 +00:00
|
|
|
convenience init() {
|
|
|
|
self.init(hasValueImage: false)
|
|
|
|
}
|
|
|
|
|
|
|
|
fileprivate init(hasValueImage: Bool) {
|
|
|
|
valueImageView = hasValueImage ? NSImageView() : nil
|
2019-01-02 19:46:27 +00:00
|
|
|
super.init(frame: CGRect.zero)
|
|
|
|
|
|
|
|
addSubview(keyLabel)
|
|
|
|
addSubview(valueLabel)
|
|
|
|
keyLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
valueLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
|
|
|
|
NSLayoutConstraint.activate([
|
|
|
|
keyLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor),
|
|
|
|
keyLabel.firstBaselineAnchor.constraint(equalTo: valueLabel.firstBaselineAnchor),
|
|
|
|
self.leadingAnchor.constraint(equalTo: keyLabel.leadingAnchor),
|
2019-01-08 20:01:44 +00:00
|
|
|
valueLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor)
|
2019-01-02 19:46:27 +00:00
|
|
|
])
|
2019-01-08 20:01:44 +00:00
|
|
|
|
2019-03-16 13:58:54 +00:00
|
|
|
let spacing: CGFloat = 5
|
|
|
|
if let valueImageView = valueImageView {
|
|
|
|
addSubview(valueImageView)
|
|
|
|
valueImageView.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
NSLayoutConstraint.activate([
|
|
|
|
valueImageView.centerYAnchor.constraint(equalTo: self.centerYAnchor),
|
|
|
|
valueImageView.leadingAnchor.constraint(equalTo: keyLabel.trailingAnchor, constant: spacing),
|
|
|
|
valueLabel.leadingAnchor.constraint(equalTo: valueImageView.trailingAnchor)
|
|
|
|
])
|
|
|
|
} else {
|
|
|
|
NSLayoutConstraint.activate([
|
|
|
|
valueLabel.leadingAnchor.constraint(equalTo: keyLabel.trailingAnchor, constant: spacing)
|
|
|
|
])
|
|
|
|
}
|
|
|
|
|
2019-01-08 20:01:44 +00:00
|
|
|
keyLabel.setContentCompressionResistancePriority(.defaultHigh + 2, for: .horizontal)
|
|
|
|
keyLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal)
|
|
|
|
valueLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
|
|
|
|
|
|
|
|
let widthConstraint = keyLabel.widthAnchor.constraint(equalToConstant: 150)
|
|
|
|
widthConstraint.priority = .defaultHigh + 1
|
|
|
|
widthConstraint.isActive = true
|
2019-01-02 19:46:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
required init?(coder decoder: NSCoder) {
|
|
|
|
fatalError("init(coder:) has not been implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
override func prepareForReuse() {
|
|
|
|
key = ""
|
|
|
|
value = ""
|
|
|
|
isKeyInBold = false
|
2021-07-29 10:27:04 +00:00
|
|
|
statusObservationToken = nil
|
|
|
|
isOnDemandEnabledObservationToken = nil
|
|
|
|
hasOnDemandRulesObservationToken = nil
|
2019-01-02 19:46:27 +00:00
|
|
|
}
|
|
|
|
}
|
2019-01-06 13:21:06 +00:00
|
|
|
|
|
|
|
class KeyValueRow: EditableKeyValueRow {
|
2019-03-16 13:58:54 +00:00
|
|
|
init() {
|
|
|
|
super.init(hasValueImage: false)
|
|
|
|
valueLabel.isEditable = false
|
|
|
|
valueLabel.isBordered = false
|
|
|
|
valueLabel.backgroundColor = .clear
|
|
|
|
}
|
|
|
|
|
|
|
|
required init?(coder decoder: NSCoder) {
|
|
|
|
fatalError("init(coder:) has not been implemented")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class KeyValueImageRow: EditableKeyValueRow {
|
|
|
|
init() {
|
|
|
|
super.init(hasValueImage: true)
|
2019-01-06 13:21:06 +00:00
|
|
|
valueLabel.isEditable = false
|
|
|
|
valueLabel.isBordered = false
|
|
|
|
valueLabel.backgroundColor = .clear
|
|
|
|
}
|
|
|
|
|
|
|
|
required init?(coder decoder: NSCoder) {
|
|
|
|
fatalError("init(coder:) has not been implemented")
|
|
|
|
}
|
|
|
|
}
|