generalizing the observing behavior
This commit is contained in:
parent
be196a289e
commit
2b378f5597
@ -124,7 +124,7 @@ import MVMCore
|
||||
didSet {
|
||||
if !updateSelectionOnly {
|
||||
layoutIfNeeded()
|
||||
(model as? CheckboxModel)?.checked = isSelected
|
||||
(model as? CheckboxModel)?.selected = isSelected
|
||||
shapeLayer?.removeAllAnimations()
|
||||
updateCheckboxUI(isSelected: isSelected, isAnimated: isAnimated)
|
||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
@ -419,8 +419,8 @@ import MVMCore
|
||||
isAnimated = model.animated
|
||||
isRound = model.round
|
||||
|
||||
if model.checked {
|
||||
checkAndBypassAnimations(selected: model.checked)
|
||||
if model.selected {
|
||||
checkAndBypassAnimations(selected: model.selected)
|
||||
}
|
||||
|
||||
isEnabled = model.enabled
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
public static var identifier: String = "checkbox"
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
public dynamic var checked: Bool = false
|
||||
public dynamic var selected: Bool = false
|
||||
public var enabled: Bool = true
|
||||
public var animated: Bool = true
|
||||
public var inverted: Bool = false
|
||||
@ -69,26 +69,22 @@
|
||||
// MARK: - Form Validation
|
||||
//--------------------------------------------------
|
||||
|
||||
public func formFieldValue() -> AnyHashable? { checked }
|
||||
public func formFieldValue() -> AnyHashable? { selected }
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Selectable Protocol
|
||||
//--------------------------------------------------
|
||||
|
||||
public func select(as isSelected: Bool) {
|
||||
checked = isSelected
|
||||
selected = isSelected
|
||||
}
|
||||
|
||||
public var selectedValue: Bool {
|
||||
checked
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(isChecked: Bool = false) {
|
||||
self.checked = isChecked
|
||||
self.selected = isChecked
|
||||
baseValue = isChecked
|
||||
}
|
||||
|
||||
@ -142,10 +138,10 @@
|
||||
}
|
||||
|
||||
if let checked = try typeContainer.decodeIfPresent(Bool.self, forKey: .checked) {
|
||||
self.checked = checked
|
||||
self.selected = checked
|
||||
}
|
||||
|
||||
baseValue = checked
|
||||
baseValue = selected
|
||||
|
||||
if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) {
|
||||
self.animated = animated
|
||||
@ -179,7 +175,7 @@
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(borderColor, forKey: .borderColor)
|
||||
try container.encode(borderWidth, forKey: .borderWidth)
|
||||
try container.encode(checked, forKey: .checked)
|
||||
try container.encode(selected, forKey: .checked)
|
||||
try container.encode(inverted, forKey: .inverted)
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
try container.encodeIfPresent(checkColor, forKey: .checkColor)
|
||||
|
||||
@ -98,7 +98,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
self.constrainKnob()
|
||||
}
|
||||
|
||||
toggleModel?.state = isOn
|
||||
toggleModel?.selected = isOn
|
||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff")
|
||||
setNeedsLayout()
|
||||
@ -381,7 +381,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
containerTintColor.off = model.offTintColor.uiColor
|
||||
knobTintColor.on = model.onKnobTintColor.uiColor
|
||||
knobTintColor.off = model.offKnobTintColor.uiColor
|
||||
isOn = model.state
|
||||
isOn = model.selected
|
||||
changeStateNoAnimation(isOn)
|
||||
isAnimated = model.animated
|
||||
isEnabled = model.enabled
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
|
||||
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol, SelectableMoleculeModel {
|
||||
public class ToggleModel: NSObject, MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol, SelectableMoleculeModel {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -15,7 +15,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
public static var identifier: String = "toggle"
|
||||
public var accessibilityIdentifier: String?
|
||||
public var backgroundColor: Color?
|
||||
public var state: Bool = false
|
||||
public dynamic var selected: Bool = false
|
||||
public var animated: Bool = true
|
||||
public var enabled: Bool = true
|
||||
public var action: ActionModelProtocol?
|
||||
@ -56,18 +56,14 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
// MARK: - Form Valdiation
|
||||
//--------------------------------------------------
|
||||
|
||||
public func formFieldValue() -> AnyHashable? { state }
|
||||
public func formFieldValue() -> AnyHashable? { selected }
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Selectable Protocol
|
||||
//--------------------------------------------------
|
||||
|
||||
public func select(as isSelected: Bool) {
|
||||
state = isSelected
|
||||
}
|
||||
|
||||
public var selectedValue: Bool {
|
||||
state
|
||||
selected = isSelected
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -75,7 +71,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(_ state: Bool) {
|
||||
self.state = state
|
||||
self.selected = state
|
||||
baseValue = state
|
||||
}
|
||||
|
||||
@ -87,7 +83,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
|
||||
self.state = state
|
||||
self.selected = state
|
||||
}
|
||||
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
@ -121,7 +117,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
|
||||
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
|
||||
|
||||
baseValue = state
|
||||
baseValue = selected
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
@ -135,7 +131,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(state, forKey: .state)
|
||||
try container.encode(selected, forKey: .state)
|
||||
try container.encode(animated, forKey: .animated)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(onTintColor, forKey: .onTintColor)
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
/// Protocol to apply to any model of a UI Control with a binary on/off nature.
|
||||
///
|
||||
/// Example classes: Checkbox or Switch.
|
||||
public protocol SelectableMoleculeModel {
|
||||
var selectedValue: Bool { get }
|
||||
@objc public protocol SelectableMoleculeModel: AnyObject {
|
||||
@objc dynamic var selected: Bool { get set }
|
||||
func select(as isSelected: Bool)
|
||||
}
|
||||
|
||||
@ -84,31 +84,33 @@ public class SelectAllBoxesBehavior: PageCustomActionHandlerBehavior, PageMolecu
|
||||
|
||||
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject) {
|
||||
|
||||
let selectableModels: [SelectableMoleculeModel] = rootMolecules.allMoleculesOfType()
|
||||
let selectableModels: [(NSObject & SelectableMoleculeModel)] = rootMolecules.allMoleculesOfType()
|
||||
|
||||
guard !selectableModels.isEmpty else { return }
|
||||
|
||||
|
||||
for model in selectableModels {
|
||||
if let checkboxModel = model as? CheckboxModel, let key = checkboxModel.fieldKey {
|
||||
if let key = (model as? FormFieldProtocol)?.fieldKey {
|
||||
valuesMirror[key] = model.selected
|
||||
setObserver(model, fieldKey: key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setObserver<T>(_ model: T, fieldKey: String) where T: (NSObject & SelectableMoleculeModel) {
|
||||
|
||||
observers[fieldKey] = model.observe(\.selected, options: [.new]) { [weak self] model, change in
|
||||
guard let self = self,
|
||||
let isChecked = change.newValue
|
||||
else { return }
|
||||
|
||||
self.valuesMirror[fieldKey] = isChecked
|
||||
|
||||
// If all are models are in the opposite state of the behavior, then realign.
|
||||
if self.selectAllIsMisaligned() {
|
||||
self.realignPageBehavior(asSelectAll: true)
|
||||
|
||||
valuesMirror[key] = checkboxModel.checked
|
||||
|
||||
observers[key] = checkboxModel.observe(\.checked, options: [.new]) { [weak self] model, change in
|
||||
guard let self = self,
|
||||
let isChecked = change.newValue,
|
||||
let key = model.fieldKey
|
||||
else { return }
|
||||
|
||||
self.valuesMirror[key] = isChecked
|
||||
|
||||
// If all are models are in the opposite state of the behavior, then realign.
|
||||
if self.selectAllIsMisaligned() {
|
||||
self.realignPageBehavior(asSelectAll: true)
|
||||
|
||||
} else if self.deselectAllIsMisaligned() {
|
||||
self.realignPageBehavior(asSelectAll: false)
|
||||
}
|
||||
}
|
||||
} else if self.deselectAllIsMisaligned() {
|
||||
self.realignPageBehavior(asSelectAll: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,13 +203,13 @@ public class SelectAllBoxesBehavior: PageCustomActionHandlerBehavior, PageMolecu
|
||||
/// - Parameter model: A model object assined to the SelectableModel protocol
|
||||
/// - Returns: Boolean determining if the passed model should be selected.
|
||||
func toSelect(model: SelectableMoleculeModel) -> Bool {
|
||||
didSelectAllState && !model.selectedValue
|
||||
didSelectAllState && !model.selected
|
||||
}
|
||||
|
||||
/// Convenience function making it easier to read if a current selectable model should be acted on.
|
||||
/// - Parameter model: A model object assined to the SelectableModel protocol
|
||||
/// - Returns: Boolean determining if the passed model should be deselected.
|
||||
func toDeselect(model: SelectableMoleculeModel) -> Bool {
|
||||
!didSelectAllState && model.selectedValue
|
||||
!didSelectAllState && model.selected
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user