Skip to content

Commit a1283db

Browse files
committed
Add support for binding NSControl.isEnabled and similar config properties
1 parent 43d55da commit a1283db

File tree

1 file changed

+46
-42
lines changed

1 file changed

+46
-42
lines changed

Sources/NSControl Glue.swift

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,25 @@ extension NSControl {
1313
@objc open dynamic override var glue: GlueForNSControl { return _glue() }
1414
}
1515

16-
public func <-- <V: UpdatableValueType>(target: GlueForNSControl.IntValueReceiver, model: V) where V.Value == Int {
17-
target.glue.setModel(model.anyUpdatableValue)
16+
public func <-- <Value, Model: UpdatableValueType>(target: GlueForNSControl.ValueSlot<Value>, model: Model) where Model.Value == Value {
17+
target.glue.setValueModel(model.anyUpdatableValue)
1818
}
19-
public func <-- <V: UpdatableValueType>(target: GlueForNSControl.IntValueReceiver, model: V) where V.Value == Int? {
20-
target.glue.setModel(model.anyUpdatableValue)
19+
public func <-- <Value, V: UpdatableValueType>(target: GlueForNSControl.ValueSlot<Value>, model: V) where V.Value == Value? {
20+
target.glue.setValueModel(model.anyUpdatableValue)
2121
}
2222

23-
public func <-- <V: UpdatableValueType>(target: GlueForNSControl.DoubleValueReceiver, model: V) where V.Value == Double {
24-
target.glue.setModel(model.anyUpdatableValue)
25-
}
26-
public func <-- <V: UpdatableValueType>(target: GlueForNSControl.DoubleValueReceiver, model: V) where V.Value == Double? {
27-
target.glue.setModel(model.anyUpdatableValue)
28-
}
29-
30-
public func <-- <V: UpdatableValueType>(target: GlueForNSControl.StringValueReceiver, model: V) where V.Value == String {
31-
target.glue.setModel(model.anyUpdatableValue)
32-
}
33-
public func <-- <V: UpdatableValueType>(target: GlueForNSControl.StringValueReceiver, model: V) where V.Value == String? {
34-
target.glue.setModel(model.anyUpdatableValue)
35-
}
36-
37-
public func <-- <V: UpdatableValueType>(target: GlueForNSControl.AttributedStringValueReceiver, model: V) where V.Value == NSAttributedString {
38-
target.glue.setModel(model.anyUpdatableValue)
39-
}
40-
public func <-- <V: UpdatableValueType>(target: GlueForNSControl.AttributedStringValueReceiver, model: V) where V.Value == NSAttributedString? {
41-
target.glue.setModel(model.anyUpdatableValue)
23+
public func <-- <Value, Model: ObservableValueType>(target: GlueForNSControl.ConfigSlot<Value>, model: Model) where Model.Value == Value {
24+
target.glue.setConfigSlot(target.keyPath, to: model.anyObservableValue)
4225
}
4326

27+
4428
open class GlueForNSControl: GlueForNSObject {
4529
private var object: NSControl { return owner as! NSControl }
4630
private var modelConnection: Connection? = nil
47-
fileprivate var model: AnyObservableValue<Any?>? = nil {
31+
fileprivate var valueModel: AnyObservableValue<Any?>? = nil {
4832
didSet {
4933
modelConnection?.disconnect()
50-
if let model = model {
34+
if let model = valueModel {
5135
modelConnection = model.values.subscribe { [unowned self] value in
5236
self.object.objectValue = value
5337
}
@@ -56,41 +40,61 @@ open class GlueForNSControl: GlueForNSObject {
5640
}
5741
}
5842
}
59-
fileprivate var updater: ((Any?) -> Bool)? = nil
43+
fileprivate var valueUpdater: ((Any?) -> Bool)? = nil
6044

61-
fileprivate func setModel<V>(_ model: AnyUpdatableValue<V>) {
62-
self.updater = { value in
45+
fileprivate func setValueModel<V>(_ model: AnyUpdatableValue<V>) {
46+
self.valueUpdater = { value in
6347
guard let v = value as? V else { return false }
6448
model.value = v
6549
return true
6650
}
67-
self.model = model.map { $0 as Any? }
51+
self.valueModel = model.map { $0 as Any? }
6852
}
6953

70-
fileprivate func setModel<V>(_ model: AnyUpdatableValue<V?>) {
71-
self.updater = { value in
54+
fileprivate func setValueModel<V>(_ model: AnyUpdatableValue<V?>) {
55+
self.valueUpdater = { value in
7256
model.value = value as? V
7357
return true
7458
}
75-
self.model = model.map { $0 as Any? }
59+
self.valueModel = model.map { $0 as Any? }
7660
}
7761

7862
@objc func controlAction(_ sender: NSControl) {
79-
if updater?(sender.objectValue) != true {
80-
sender.objectValue = model?.value
63+
if valueUpdater?(sender.objectValue) != true {
64+
sender.objectValue = valueModel?.value
8165
}
8266
}
8367

84-
public struct IntValueReceiver { fileprivate let glue: GlueForNSControl }
85-
public var intValue: IntValueReceiver { return IntValueReceiver(glue: self) }
68+
public struct ValueSlot<Value> {
69+
fileprivate let glue: GlueForNSControl
70+
}
71+
72+
public var intValue: ValueSlot<Int> { return ValueSlot<Int>(glue: self) }
73+
public var doubleValue: ValueSlot<Double> { return ValueSlot(glue: self) }
74+
public var stringValue: ValueSlot<String> { return ValueSlot(glue: self) }
75+
public var attributedStringValue: ValueSlot<NSAttributedString> { return ValueSlot(glue: self) }
8676

87-
public struct DoubleValueReceiver { fileprivate let glue: GlueForNSControl }
88-
public var doubleValue: DoubleValueReceiver { return DoubleValueReceiver(glue: self) }
77+
public struct ConfigSlot<Value> {
78+
fileprivate let glue: GlueForNSControl
79+
fileprivate let keyPath: ReferenceWritableKeyPath<NSControl, Value>
80+
}
81+
82+
var configModels: [AnyKeyPath: Connection] = [:]
8983

90-
public struct StringValueReceiver { fileprivate let glue: GlueForNSControl }
91-
public var stringValue: StringValueReceiver { return StringValueReceiver(glue: self) }
84+
func setConfigSlot<Value>(_ keyPath: ReferenceWritableKeyPath<NSControl, Value>, to model: AnyObservableValue<Value>) {
85+
let connection = model.values.subscribe { [unowned object] value in
86+
object[keyPath: keyPath] = value
87+
_ = object
88+
}
89+
configModels.updateValue(connection, forKey: keyPath)?.disconnect()
90+
}
9291

93-
public struct AttributedStringValueReceiver { fileprivate let glue: GlueForNSControl }
94-
public var attributedStringValue: AttributedStringValueReceiver { return AttributedStringValueReceiver(glue: self) }
92+
public var isEnabled: ConfigSlot<Bool> { return ConfigSlot(glue: self, keyPath: \.isEnabled) }
93+
public var alignment: ConfigSlot<NSTextAlignment> { return ConfigSlot(glue: self, keyPath: \.alignment) }
94+
public var font: ConfigSlot<NSFont?> { return ConfigSlot(glue: self, keyPath: \.font) }
95+
public var lineBreakMode: ConfigSlot<NSParagraphStyle.LineBreakMode> { return ConfigSlot(glue: self, keyPath: \.lineBreakMode) }
96+
public var usesSingleLineMode: ConfigSlot<Bool> { return ConfigSlot(glue: self, keyPath: \.usesSingleLineMode) }
97+
public var formatter: ConfigSlot<Formatter?> { return ConfigSlot(glue: self, keyPath: \.formatter) }
98+
public var baseWritingDirection: ConfigSlot<NSWritingDirection> { return ConfigSlot(glue: self, keyPath: \.baseWritingDirection) }
9599
}
96100
#endif

0 commit comments

Comments
 (0)