diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift index eb7266a9..39a578ba 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift @@ -7,54 +7,121 @@ // import UIKit +import VDS +@objcMembers public class RadioButtonLabel: VDS.RadioButtonItem, RadioButtonSelectionHelperProtocol, VDSMoleculeViewProtocol, MFButtonProtocol { -@objcMembers public class RadioButtonLabel: View { - - public let radioButton = RadioButton() - var delegateObject: MVMCoreUIDelegateObject? - let label = Label() - - public override func updateView(_ size: CGFloat) { - super.updateView(size) - radioButton.updateView(size) - label.updateView(size) - } + //------------------------------------------------------ + // MARK: - Properties + //------------------------------------------------------ + open var viewModel: RadioButtonLabelModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? - open override func setupView() { - super.setupView() + open var radioButtonModel: RadioButtonModel { + viewModel.radioButton + } - addSubview(radioButton) - radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true - radioButton.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne).isActive = true - layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true - radioButton.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor).isActive = true + // Form Validation + var fieldKey: String? + var fieldValue: JSONValue? + var groupName: String? - if let rightView = createRightView() { - addSubview(rightView) - rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: Padding.Component.gutterForApplicationWidth).isActive = true - rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true - - var constraint = rightView.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne) - constraint.priority = .defaultHigh - constraint.isActive = true - - constraint = layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: rightView.bottomAnchor, constant: PaddingOne) - constraint.priority = .defaultHigh - constraint.isActive = true - layoutMarginsGuide.centerYAnchor.constraint(equalTo: rightView.centerYAnchor).isActive = true + open override var isSelected: Bool { + didSet { + radioButtonModel.state = isSelected + if oldValue != isSelected { + sendActions(for: .valueChanged) + } } } - func createRightView() -> Container? { - let rightView = Container(andContain: label) - return rightView + lazy public var radioGroupName: String? = { viewModel.radioButton.fieldKey }() + + lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = { + + guard let radioGroupName = radioGroupName, + let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName] + else { return nil } + + return radioButtonModel + }() + + //-------------------------------------------------- + // MARK: - Life Cycle + //-------------------------------------------------- + @objc open func updateView(_ size: CGFloat) {} + + open override func toggle() { + guard !isSelected, isEnabled else { return } + + //removed error + if showError && isSelected == false { + showError.toggle() + } + + let wasPreviouslySelected = isSelected + if let radioButtonSelectionHelper { + radioButtonSelectionHelper.selected(self) + } else { + isSelected = !isSelected + } + + if let actionModel = viewModel.radioButton.action, isSelected, !wasPreviouslySelected { + Task(priority: .userInitiated) { + try await Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: viewModel) + } + } + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + } - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let radioButtonLabelModel = model as? RadioButtonLabelModel else { return } - - radioButton.set(with: radioButtonLabelModel.radioButton, delegateObject, additionalData) - label.set(with: radioButtonLabelModel.label, delegateObject, additionalData) + //-------------------------------------------------- + // MARK: - Atomic + //-------------------------------------------------- + public func viewModelDidUpdate() { + surface = viewModel.surface + + updateRadioButton() + + //primary label + labelText = viewModel.label.text + if let attributes = viewModel.label.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) { + labelTextAttributes = attributes + } + + //secondary label + if let subTitleModel = viewModel.subTitle { + childText = subTitleModel.text + if let attributes = subTitleModel.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) { + childTextAttributes = attributes + } + } } + + public func updateRadioButton() { + + if let fieldKey = viewModel.radioButton.fieldKey { + self.fieldKey = fieldKey + } + + //properties + isEnabled = viewModel.radioButton.enabled && !viewModel.radioButton.readOnly + isSelected = viewModel.radioButton.state + + //forms + RadioButtonSelectionHelper.setupForRadioButtonGroup(viewModel.radioButton, self, delegateObject: delegateObject) + + //events + viewModel.radioButton.updateUI = { + MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in + guard let self = self else { return } + let isValid = viewModel.radioButton.isValid ?? true + showError = !isValid + errorText = viewModel.radioButton.errorMessage + isEnabled = viewModel.radioButton.enabled + }) + } + } + } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift index 571848dc..0f4a4be6 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift @@ -8,8 +8,9 @@ import Foundation import MVMCore +import VDS -@objcMembers public class RadioButtonLabelModel: MoleculeModelProtocol { +@objcMembers public class RadioButtonLabelModel: MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -21,14 +22,23 @@ import MVMCore public var moleculeName: String = RadioButtonLabelModel.identifier public var radioButton: RadioButtonModel public var label: LabelModel + public var subTitle: LabelModel? + public var inverted: Bool? = false + public var surface: Surface { inverted ?? false ? .dark : .light } + public var children: [MoleculeModelProtocol] { + guard let subTitle else { return [radioButton, label] } + return [radioButton, label, subTitle] + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- - public init(radioButton: RadioButtonModel, label: LabelModel) { + public init(radioButton: RadioButtonModel, label: LabelModel, subTitle: LabelModel?) { self.radioButton = radioButton self.label = label + self.subTitle = subTitle } }