diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index a5fedef0..1a968b7a 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -90,6 +90,9 @@ import UIKit /// The action performed when tapped. func tapAction() { + if !isEnabled { + return + } if let radioButtonModel = radioButtonSelectionHelper { radioButtonModel.selected(self) } else { diff --git a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift index a7c59cd3..a7d85f86 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift @@ -14,8 +14,8 @@ import Foundation // MARK: - Outlets //------------------------------------------------------ - let leftTextLabel = Label.commonLabelB1(true) - let rightTextLabel = Label.commonLabelB1(true) + let leftTextLabel = Label.createLabelBoldBodySmall(true) + let rightTextLabel = Label.createLabelBoldBodySmall(true) //------------------------------------------------------ // MARK: - Constraints @@ -23,6 +23,29 @@ import Foundation var rightTextLabelLeading: NSLayoutConstraint? var leftTextLabelTrailing: NSLayoutConstraint? + var rightTextLabelTrailing: NSLayoutConstraint? + + private func constrainLeftLabelOnly() { + + deactivateMiddleConstraint() + leftTextLabelTrailing?.isActive = false + leftTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor) + leftTextLabelTrailing?.isActive = true + } + + private func constrainRightLabelOnly() { + + deactivateMiddleConstraint() + rightTextLabelLeading?.isActive = false + rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) + rightTextLabelLeading?.isActive = true + } + + private func deactivateMiddleConstraint() { + + leftTextLabelTrailing?.isActive = false + rightTextLabelLeading?.isActive = false + } //------------------------------------------------------ // MARK: - Initialization @@ -43,8 +66,6 @@ import Foundation override open func setupView() { super.setupView() - guard subviews.isEmpty else { return } - addSubview(leftTextLabel) addSubview(rightTextLabel) @@ -67,7 +88,7 @@ import Foundation // Resolves text layout issues found between both dynamically sized labels, number is not exact but performs as required. if leftTextLabel.hasText && rightTextLabel.hasText { let padding = MFStyler.defaultHorizontalPadding(forSize: size) * 2 - let maximumTextWidth = (size - (padding + 16)) * 0.4 + let maximumTextWidth = (size - (padding + Padding.Four)) * 0.4 // Subtracting 10 resolves issues of SE and iPad rightTextLabel.preferredMaxLayoutWidth = round(maximumTextWidth) - 10 } else { @@ -84,57 +105,38 @@ import Foundation leftTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true leftTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true - let leftTextBottom = leftTextLabel.bottomAnchor.constraint(equalTo: bottomAnchor) + let leftTextBottom = bottomAnchor.constraint(equalTo: leftTextLabel.bottomAnchor) leftTextBottom.priority = UILayoutPriority(249) leftTextBottom.isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: leftTextLabel.bottomAnchor).isActive = true - rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor, constant: 16) + rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor, constant: Padding.Four) rightTextLabelLeading?.isActive = true rightTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true - let rightLayout = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor) - rightLayout.priority = UILayoutPriority(rawValue: 995) - rightLayout.isActive = true - let rightTextBottom = rightTextLabel.bottomAnchor.constraint(equalTo: bottomAnchor) + rightTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor) + rightTextLabelTrailing?.isActive = true + + let rightTextBottom = bottomAnchor.constraint(equalTo: rightTextLabel.bottomAnchor) rightTextBottom.priority = UILayoutPriority(rawValue: 249) rightTextBottom.isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: rightTextLabel.bottomAnchor).isActive = true - let leftTextWidth = leftTextLabel.widthAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.widthAnchor, multiplier: 0.6) + let leftTextWidth = leftTextLabel.widthAnchor.constraint(equalTo: layoutMarginsGuide.widthAnchor, multiplier: 0.6) leftTextWidth.priority = UILayoutPriority(rawValue: 995) leftTextWidth.isActive = true - let rightTextWidth = rightTextLabel.widthAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.widthAnchor, multiplier: 0.4) - rightTextWidth.priority = UILayoutPriority(rawValue: 906) + let rightTextWidth = rightTextLabel.widthAnchor.constraint(equalTo: layoutMarginsGuide.widthAnchor, multiplier: 0.4) + rightTextWidth.priority = UILayoutPriority(rawValue: 995) rightTextWidth.isActive = true - leftTextLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal) - rightTextLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal) - - leftTextLabel.setContentHuggingPriority(.required, for: .vertical) - rightTextLabel.setContentHuggingPriority(.required, for: .vertical) - + rightTextLabel.setContentHuggingPriority(.required, for: .horizontal) leftTextLabel.setContentCompressionResistancePriority(.required, for: .vertical) rightTextLabel.setContentCompressionResistancePriority(.required, for: .vertical) - rightTextLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 902), for: .horizontal) - } - - private func constrainLeftLabel() { - - deactivateMiddleConstraint() - leftTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor) - leftTextLabelTrailing?.isActive = true - } - - private func constrainRightLabel() { - - deactivateMiddleConstraint() - rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) - rightTextLabelLeading?.isActive = true + rightTextLabel.setContentCompressionResistancePriority(.required, for: .horizontal) } override open func reset() { @@ -144,31 +146,31 @@ import Foundation constrainBothLabels() leftTextLabel.text = "" rightTextLabel.text = "" + leftTextLabel.textAlignment = .left + rightTextLabel.textAlignment = .right backgroundColor = nil } - private func deactivateMiddleConstraint() { - - leftTextLabelTrailing?.isActive = false - rightTextLabelLeading?.isActive = false - } - //------------------------------------------------------ // MARK: - Atomization //------------------------------------------------------ open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - guard let leftRightLabelModel = model as? LeftRightLabelModel else { - return - } + + guard let leftRightLabelModel = model as? LeftRightLabelModel else { return } + leftTextLabel.set(with: leftRightLabelModel.leftText, delegateObject, additionalData) rightTextLabel.setOptional(with: leftRightLabelModel.rightText, delegateObject, additionalData) - + + // Label defaults to .left if no textAlignment value is provided in model. + rightTextLabel.textAlignment = leftRightLabelModel.rightText?.textAlignment ?? .right + if !leftTextLabel.hasText { - constrainRightLabel() + constrainRightLabelOnly() + } else if !rightTextLabel.hasText { - constrainLeftLabel() + constrainLeftLabelOnly() } } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index 956c2afc..75e9675a 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -25,13 +25,13 @@ public typealias ActionBlockConfirmation = () -> (Bool) //-------------------------------------------------- /// Holds the on and off colors for the container. - public var containerTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmGreen, off: .mvmBlack) + public var containerTintColor: (on: UIColor, off: UIColor) = (on: .mvmGreen, off: .mvmBlack) /// Holds the on and off colors for the knob. - public var knobTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmWhite, off: .mvmWhite) + public var knobTintColor: (on: UIColor, off: UIColor) = (on: .mvmWhite, off: .mvmWhite) /// Holds the on and off colors for the disabled state.. - public var disabledTintColor: (container: UIColor?, knob: UIColor?)? = (container: .mvmCoolGray3, knob: .mvmWhite) + public var disabledTintColor: (container: UIColor, knob: UIColor) = (container: .mvmCoolGray3, knob: .mvmWhite) /// Set this flag to false if you do not want to animate state changes. public var isAnimated = true @@ -62,8 +62,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) didSet { isUserInteractionEnabled = isEnabled changeStateNoAnimation(isEnabled ? isOn : false) - backgroundColor = isEnabled ? containerTintColor?.off : disabledTintColor?.container - knobView.backgroundColor = isEnabled ? knobTintColor?.off : disabledTintColor?.knob + backgroundColor = isEnabled ? (isOn ? containerTintColor.on : containerTintColor.off) : disabledTintColor.container + knobView.backgroundColor = isEnabled ? (isOn ? knobTintColor.on : knobTintColor.off) : disabledTintColor.knob } } @@ -80,12 +80,12 @@ public typealias ActionBlockConfirmation = () -> (Bool) if isAnimated { UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: { if self.isOn { - self.knobView.backgroundColor = self.knobTintColor?.on - self.backgroundColor = self.containerTintColor?.on + self.knobView.backgroundColor = self.knobTintColor.on + self.backgroundColor = self.containerTintColor.on } else { - self.knobView.backgroundColor = self.knobTintColor?.off - self.backgroundColor = self.containerTintColor?.off + self.knobView.backgroundColor = self.knobTintColor.off + self.backgroundColor = self.containerTintColor.off } }, completion: nil) @@ -96,12 +96,12 @@ public typealias ActionBlockConfirmation = () -> (Bool) }, completion: nil) } else { - backgroundColor = isOn ? containerTintColor?.on : containerTintColor?.off - knobView.backgroundColor = isOn ? knobTintColor?.on : knobTintColor?.off + backgroundColor = isOn ? containerTintColor.on : containerTintColor.off + knobView.backgroundColor = isOn ? knobTintColor.on : knobTintColor.off self.constrainKnob() } - (model as? ToggleModel)?.state = isOn + toggleModel?.state = isOn _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") setNeedsLayout() @@ -109,6 +109,10 @@ public typealias ActionBlockConfirmation = () -> (Bool) } } + public var toggleModel: ToggleModel? { + return model as? ToggleModel + } + //-------------------------------------------------- // MARK: - Delegate //-------------------------------------------------- @@ -189,7 +193,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) public override func setupView() { super.setupView() - guard subviews.isEmpty else { return } + isAccessibilityElement = true accessibilityTraits = .button accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint") @@ -202,7 +206,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) widthConstraint?.isActive = true layer.cornerRadius = Self.containerSize.height / 2.0 - backgroundColor = containerTintColor?.off + backgroundColor = containerTintColor.off addSubview(knobView) @@ -222,9 +226,9 @@ public typealias ActionBlockConfirmation = () -> (Bool) public override func reset() { super.reset() - backgroundColor = containerTintColor?.off - knobView.backgroundColor = knobTintColor?.off - isAnimated = false + backgroundColor = containerTintColor.off + knobView.backgroundColor = knobTintColor.off + isAnimated = true isOn = false constrainKnob() didToggleAction = nil @@ -344,26 +348,14 @@ public typealias ActionBlockConfirmation = () -> (Bool) FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - if let color = model.onTintColor?.uiColor { - containerTintColor?.on = color - } - - if let color = model.offTintColor?.uiColor { - containerTintColor?.off = color - } - - if let color = model.onKnobTintColor?.uiColor { - knobTintColor?.on = color - } - - if let color = model.offKnobTintColor?.uiColor { - knobTintColor?.off = color - } - + containerTintColor.on = model.onTintColor.uiColor + containerTintColor.off = model.offTintColor.uiColor + knobTintColor.on = model.onKnobTintColor.uiColor + knobTintColor.off = model.offKnobTintColor.uiColor changeStateNoAnimation(model.state) isAnimated = model.animated isEnabled = model.enabled - + if let actionMap = model.action?.toJSON() { didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift index 9eb2f4b5..b39003d2 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift @@ -8,8 +8,12 @@ import UIKit -public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol { +public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "toggle" public var backgroundColor: Color? public var state: Bool = false @@ -18,10 +22,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo public var action: ActionModelProtocol? public var alternateAction: ActionModelProtocol? public var accessibilityText: String? - public var onTintColor: Color? - public var offTintColor: Color? - public var onKnobTintColor: Color? - public var offKnobTintColor: Color? + public var onTintColor: Color = Color(uiColor: .mvmGreen) + public var offTintColor: Color = Color(uiColor: .mvmBlack) + public var onKnobTintColor: Color = Color(uiColor: .mvmWhite) + public var offKnobTintColor: Color = Color(uiColor: .mvmWhite) public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName @@ -75,19 +79,35 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { self.state = state } + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } + if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) { self.animated = animated } + action = try typeContainer.decodeModelIfPresent(codingKey: .action) alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor) - offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor) - onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor) - offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor) + + if let onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor) { + self.onTintColor = onTintColor + } + + if let offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor) { + self.offTintColor = offTintColor + } + + if let onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor) { + self.onKnobTintColor = onKnobTintColor + } + + if let offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor) { + self.offKnobTintColor = offKnobTintColor + } + accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) baseValue = state @@ -106,10 +126,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo try container.encode(state, forKey: .state) try container.encode(animated, forKey: .animated) try container.encode(enabled, forKey: .enabled) - try container.encodeIfPresent(onTintColor, forKey: .onTintColor) - try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor) - try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor) - try container.encodeIfPresent(offKnobTintColor, forKey: .offKnobTintColor) + try container.encode(onTintColor, forKey: .onTintColor) + try container.encode(onKnobTintColor, forKey: .onKnobTintColor) + try container.encode(onKnobTintColor, forKey: .onKnobTintColor) + try container.encode(offKnobTintColor, forKey: .offKnobTintColor) try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(groupName, forKey: .groupName) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift index 4597a0b9..7bf1ff6a 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift @@ -71,9 +71,6 @@ import UIKit } public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - - if radioButton.isEnabled { - radioButton.tapAction() - } + radioButton.tapAction() } }