From 8a12bf12c2e3f25c372cd9bc8c622d8a3b6e130d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 9 Jul 2024 10:21:55 -0500 Subject: [PATCH 1/7] refactored models Signed-off-by: Matt Bruce --- .../Atoms/Selectors/RadioBoxModel.swift | 18 +++-- .../Atoms/Selectors/RadioBoxesModel.swift | 77 ++++++++----------- 2 files changed, 42 insertions(+), 53 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift index acec6e83..87326c7d 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift @@ -6,6 +6,7 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // import MVMCore +import VDS @objcMembers public class RadioBoxModel: MoleculeModelProtocol, EnableableModelProtocol { //-------------------------------------------------- @@ -17,15 +18,17 @@ import MVMCore public var text: String public var subText: String? + public var subTextRight: String? public var backgroundColor: Color? public var accessibilityIdentifier: String? - public var selectedAccentColor: Color? public var selected: Bool = false public var enabled: Bool = true public var readOnly: Bool = false public var strikethrough: Bool = false public var fieldValue: String? public var action: ActionModelProtocol? + public var inverted: Bool = false + public var surface: Surface { inverted ? .dark : .light } //-------------------------------------------------- // MARK: - Keys @@ -36,7 +39,7 @@ import MVMCore case moleculeName case text case subText - case selectedAccentColor + case subTextRight case backgroundColor case accessibilityIdentifier case selected @@ -45,6 +48,7 @@ import MVMCore case fieldValue case action case readOnly + case inverted } //-------------------------------------------------- @@ -65,8 +69,7 @@ import MVMCore id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString text = try typeContainer.decode(String.self, forKey: .text) subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText) - selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + subTextRight = try typeContainer.decodeIfPresent(String.self, forKey: .subTextRight) accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) { @@ -80,6 +83,10 @@ import MVMCore strikethrough = isStrikeTrough } + if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { + self.inverted = inverted + } + fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) action = try typeContainer.decodeModelIfPresent(codingKey: .action) } @@ -90,8 +97,7 @@ import MVMCore try container.encode(moleculeName, forKey: .moleculeName) try container.encode(text, forKey: .text) try container.encodeIfPresent(subText, forKey: .subText) - try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(subTextRight, forKey: .subTextRight) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encode(selected, forKey: .selected) try container.encode(enabled, forKey: .enabled) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index f1c652f7..105f9645 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -6,32 +6,38 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // import MVMCore +import VDS -@objcMembers public class RadioBoxesModel: MoleculeModelProtocol, FormFieldProtocol { +@objcMembers public class RadioBoxesModel: FormFieldModel { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public static var identifier: String = "radioBoxes" - public var id: String = UUID().uuidString + public override static var identifier: String { "radioBoxes" } public var boxes: [RadioBoxModel] - public var backgroundColor: Color? - public var accessibilityIdentifier: String? - public var selectedAccentColor: Color? - public var boxesColor: Color? - public var fieldKey: String? - public var groupName: String = FormValidator.defaultGroupName - public var baseValue: AnyHashable? - public var enabled: Bool = true - public var readOnly: Bool = false - + public var inverted: Bool = false + public var surface: Surface { inverted ? .dark : .light } + + public var selectorModels: [VDS.RadioBoxGroup.RadioBoxItemModel] { + boxes.compactMap({ item in + var radioBox = RadioBoxGroup.RadioBoxItemModel() + radioBox.text = item.text + radioBox.subText = item.subText + radioBox.subTextRight = item.subTextRight + radioBox.surface = surface + radioBox.selected = item.selected + radioBox.strikethrough = item.strikethrough + radioBox.disabled = !(item.enabled && !item.readOnly) + return radioBox + }) + } //-------------------------------------------------- // MARK: - Form Validation //-------------------------------------------------- /// Returns the fieldValue of the selected box, otherwise the text of the selected box. - public func formFieldValue() -> AnyHashable? { + public override func formFieldValue() -> AnyHashable? { guard enabled else { return nil } let selectedBox = boxes.first { (box) -> Bool in return box.selected @@ -42,7 +48,7 @@ import MVMCore //-------------------------------------------------- // MARK: - Server Value //-------------------------------------------------- - open func formFieldServerValue() -> AnyHashable? { + open override func formFieldServerValue() -> AnyHashable? { return formFieldValue() } @@ -51,17 +57,8 @@ import MVMCore //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case id - case moleculeName - case enabled - case readOnly - case selectedAccentColor - case backgroundColor - case accessibilityIdentifier - case boxesColor case boxes - case fieldKey - case groupName + case inverted } //-------------------------------------------------- @@ -69,7 +66,8 @@ import MVMCore //-------------------------------------------------- public init(with boxes: [RadioBoxModel]){ - self.boxes = boxes + self.boxes = boxes + super.init() } //-------------------------------------------------- @@ -78,32 +76,17 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString - selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) - boxesColor = try typeContainer.decodeIfPresent(Color.self, forKey: .boxesColor) boxes = try typeContainer.decode([RadioBoxModel].self, forKey: .boxes) - fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) - if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { - self.groupName = groupName + if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { + self.inverted = inverted } - enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true - readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false - baseValue = formFieldValue() + try super.init(from: decoder) } - public func encode(to encoder: Encoder) throws { + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(id, forKey: .id) - try container.encode(moleculeName, forKey: .moleculeName) try container.encode(boxes, forKey: .boxes) - try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) - try container.encodeIfPresent(fieldKey, forKey: .fieldKey) - try container.encode(groupName, forKey: .groupName) - try container.encode(enabled, forKey: .enabled) - try container.encode(readOnly, forKey: .readOnly) + try container.encode(inverted, forKey: .inverted) } } From 8c5840fba326dcf5fbbaf7782d7bf8b3bc63b74d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 9 Jul 2024 10:23:05 -0500 Subject: [PATCH 2/7] views updated for model changes Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Selectors/RadioBox.swift | 246 +++--------------- .../Atomic/Atoms/Selectors/RadioBoxes.swift | 202 ++++---------- 2 files changed, 79 insertions(+), 369 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift index 9fb6b354..ce890bc3 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift @@ -5,243 +5,57 @@ // Created by Scott Pfeil on 4/9/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // +import VDS - -open class RadioBox: Control, MFButtonProtocol { - //-------------------------------------------------- +open class RadioBox: VDS.RadioBoxItem, VDSMoleculeViewProtocol, MFButtonProtocol { + //------------------------------------------------------ // MARK: - Properties - //-------------------------------------------------- - - public let label = Label(fontStyle: .RegularBodySmall) - public let subTextLabel = Label(fontStyle: .RegularMicro) - public var isOutOfStock = false - public var accentColor = UIColor.mvmRed + //------------------------------------------------------ + open var viewModel: RadioBoxModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? - public let innerPadding: CGFloat = 12.0 + public var isOutOfStock: Bool { viewModel.strikethrough } - private var borderLayer: CALayer? - private var strikeLayer: CALayer? - private var maskLayer: CALayer? - - public var subTextLabelHeightConstraint: NSLayoutConstraint? - - private var delegateObject: MVMCoreUIDelegateObject? - var additionalData: [AnyHashable: Any]? - - public var radioBoxModel: RadioBoxModel? { - model as? RadioBoxModel - } - - public override var isSelected: Bool { - didSet { updateAccessibility() } - } - - public override var isEnabled: Bool { - didSet { updateAccessibility() } - } - //-------------------------------------------------- // MARK: - MVMCoreViewProtocol //-------------------------------------------------- - open override func updateView(_ size: CGFloat) { - super.updateView(size) - label.updateView(size) - subTextLabel.updateView(size) - layer.setNeedsDisplay() - } + open func updateView(_ size: CGFloat) {} - open override func setupView() { - super.setupView() - - layer.delegate = self - layer.borderColor = UIColor.mvmCoolGray6.cgColor - layer.borderWidth = 1 - - label.numberOfLines = 1 - addSubview(label) - NSLayoutConstraint.constraintPinSubview(label, pinTop: true, topConstant: innerPadding, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: innerPadding, pinRight: true, rightConstant: innerPadding) - - subTextLabel.textColor = .mvmCoolGray6 - subTextLabel.numberOfLines = 1 - addSubview(subTextLabel) - NSLayoutConstraint.constraintPinSubview(subTextLabel, pinTop: false, topConstant:0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: innerPadding, pinRight: true, rightConstant: innerPadding) - bottomAnchor.constraint(greaterThanOrEqualTo: subTextLabel.bottomAnchor, constant: innerPadding).isActive = true - subTextLabel.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 2).isActive = true - subTextLabelHeightConstraint = subTextLabel.heightAnchor.constraint(equalToConstant: 0) - subTextLabelHeightConstraint?.isActive = true - + open override func setup() { + super.setup() + addTarget(self, action: #selector(selectBox), for: .touchUpInside) + } + + public func viewModelDidUpdate() { + + text = viewModel.text + subText = viewModel.subText + subTextRight = viewModel.subTextRight + strikethrough = viewModel.strikethrough + isSelected = viewModel.selected + isEnabled = viewModel.enabled && !viewModel.readOnly - isAccessibilityElement = true - } - - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.set(with: model, delegateObject, additionalData) - guard let model = model as? RadioBoxModel else { return } - self.delegateObject = delegateObject - self.additionalData = additionalData - label.text = model.text - subTextLabel.text = model.subText - isOutOfStock = model.strikethrough - subTextLabelHeightConstraint?.isActive = (subTextLabel.text?.count ?? 0) == 0 - if let color = model.selectedAccentColor?.uiColor { - accentColor = color + onChange = { [weak self] _ in + if let radioBoxModel = self?.viewModel, let actionModel = radioBoxModel.action { + Task(priority: .userInitiated) { [weak self] in + guard let self else { return } + try await Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: radioBoxModel) + } + } } - isSelected = model.selected - isEnabled = model.enabled && !model.readOnly - } - - open override func reset() { - super.reset() - backgroundColor = .white - accentColor = .mvmRed - } - - //-------------------------------------------------- - // MARK: - State Handling - //-------------------------------------------------- - - open override func draw(_ layer: CALayer, in ctx: CGContext) { - // Draw the strikethrough - strikeLayer?.removeFromSuperlayer() - if isOutOfStock { - let line = getStrikeThrough(color: isSelected ? .black : .mvmCoolGray6, thickness: 1) - layer.addSublayer(line) - strikeLayer = line - } - - // Draw the border - borderLayer?.removeFromSuperlayer() - if isSelected { - layer.borderWidth = 0 - let border = getSelectedBorder() - layer.addSublayer(border) - borderLayer = border - } else { - layer.borderWidth = 1 - } - - // Handle Mask - maskLayer?.removeFromSuperlayer() - if !isEnabled { - let mask = getMaskLayer() - layer.mask = mask - maskLayer = mask - } - } - - open override func layoutSubviews() { - super.layoutSubviews() - // Accounts for any size changes - layer.setNeedsDisplay() } @objc open func selectBox() { guard isEnabled, !isSelected else { return } isSelected = true - radioBoxModel?.selected = isSelected - if let radioBoxModel = radioBoxModel, let actionModel = radioBoxModel.action { - Task(priority: .userInitiated) { - try await Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: radioBoxModel) - } - } - layer.setNeedsDisplay() + viewModel.selected = isSelected } @objc open func deselectBox() { - isSelected = false - radioBoxModel?.selected = isSelected - layer.setNeedsDisplay() - } - - /// Gets the selected state border - func getSelectedBorder() -> CAShapeLayer { - let layer = CAShapeLayer() - - let topLineWidth: CGFloat = 4 - let topLinePath = UIBezierPath() - topLinePath.lineWidth = topLineWidth - topLinePath.move(to: CGPoint(x: 0, y: topLineWidth / 2.0)) - topLinePath.addLine(to: CGPoint(x: bounds.width, y: topLineWidth / 2.0)) - - let topLineLayer = CAShapeLayer() - topLineLayer.fillColor = nil - topLineLayer.strokeColor = accentColor.cgColor - topLineLayer.lineWidth = 4 - topLineLayer.path = topLinePath.cgPath - layer.addSublayer(topLineLayer) - let lineWidth: CGFloat = 1 - let halfLineWidth: CGFloat = 0.5 - let linePath = UIBezierPath() - linePath.move(to: CGPoint(x: halfLineWidth, y: topLineWidth)) - linePath.addLine(to: CGPoint(x: halfLineWidth, y: bounds.height)) - linePath.move(to: CGPoint(x: 0, y: bounds.height - halfLineWidth)) - linePath.addLine(to: CGPoint(x: bounds.width, y: bounds.height - halfLineWidth)) - linePath.move(to: CGPoint(x: bounds.width - halfLineWidth, y: bounds.height)) - linePath.addLine(to: CGPoint(x: bounds.width - halfLineWidth, y: topLineWidth)) - - let borderLayer = CAShapeLayer() - borderLayer.fillColor = nil - borderLayer.strokeColor = UIColor.black.cgColor - borderLayer.lineWidth = lineWidth - borderLayer.path = linePath.cgPath - layer.addSublayer(borderLayer) - - return layer - } - - /// Adds a border to edge - func getStrikeThrough(color: UIColor, thickness: CGFloat) -> CAShapeLayer { - let border = CAShapeLayer() - border.name = "strikethrough" - border.fillColor = nil - border.opacity = 1.0 - border.lineWidth = thickness - border.strokeColor = color.cgColor - - let linePath = UIBezierPath() - linePath.move(to: CGPoint(x: 0, y: bounds.height)) - linePath.addLine(to: CGPoint(x: bounds.width, y: 0)) - border.path = linePath.cgPath - return border - } - - func getMaskLayer() -> CALayer { - let mask = CALayer() - mask.backgroundColor = UIColor.white.cgColor - mask.opacity = 0.3 - mask.frame = bounds - return mask - } - - //-------------------------------------------------- - // MARK: - Accessibility - //-------------------------------------------------- - - public func updateAccessibility() { - - var message = "" - - if let labelText = label.text, label.hasText { - message += labelText + ", " - } - - if let subLabelText = subTextLabel.text, subTextLabel.hasText { - message += subLabelText + ", " - } - - accessibilityLabel = message - accessibilityTraits = .button - - if isSelected { - accessibilityTraits.insert(.selected) - } - - if !isEnabled { - accessibilityTraits.insert(.notEnabled) - } } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift index ced00073..7ba1f755 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift @@ -7,172 +7,68 @@ // import Foundation +import VDS public protocol RadioBoxSelectionDelegate: AnyObject { func selected(radioBox: RadioBoxModel) } -open class RadioBoxes: View { - - public var collectionView: CollectionView! - public var collectionViewHeight: NSLayoutConstraint! - private let boxWidth: CGFloat = 151.0 - private let boxHeight: CGFloat = 64.0 - private var itemSpacing: CGFloat = 12.0 - private var numberOfColumns: CGFloat = 2.0 - private var radioBoxesModel: RadioBoxesModel? { - return model as? RadioBoxesModel - } - public weak var radioDelegate: RadioBoxSelectionDelegate? - private var delegateObject: MVMCoreUIDelegateObject? +open class RadioBoxes: VDS.RadioBoxGroup, VDSMoleculeViewProtocol { + //------------------------------------------------------ + // MARK: - Properties + //------------------------------------------------------ + open var viewModel: RadioBoxesModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? + + // Form Validation + var fieldKey: String? + var fieldValue: JSONValue? + var groupName: String? + /// The models for the molecules. public var boxes: [RadioBoxModel]? + public weak var radioDelegate: RadioBoxSelectionDelegate? - private var size: CGFloat? - - open override func layoutSubviews() { - super.layoutSubviews() - // Accounts for any collection size changes - DispatchQueue.main.async { - self.collectionView.collectionViewLayout.invalidateLayout() - } +// TODO: this matches the current accessibility however not what was passed by Barbara's team. +// open override var items: [RadioBoxItem] { +// didSet { +// let total = items.count +// for (index, radioBoxItem) in items.enumerated() { +// radioBoxItem.selectorView.bridge_accessibilityValueBlock = { +// guard let format = MVMCoreUIUtility.hardcodedString(withKey: "index_string_of_total"), +// let indexString = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: index + 1)) else { return ""} +// return String(format: format, indexString, total) +// } +// } +// } +// } + + open override func setup() { + super.setup() + } - - open func updateAccessibilityValue(collectionView: UICollectionView, cell: RadioBoxCollectionViewCell, indexPath: IndexPath) { - guard let format = MVMCoreUIUtility.hardcodedString(withKey: "index_string_of_total"), - let indexString = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: indexPath.row + 1)) else { return } - let total = self.collectionView(collectionView, numberOfItemsInSection: indexPath.section) - cell.accessibilityValue = String(format: format, indexString, total) - } - - // MARK: - MVMCoreViewProtocol - open override func setupView() { - super.setupView() - collectionView = createCollectionView() - addSubview(collectionView) - NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView) - collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 300) - collectionViewHeight?.isActive = true - } - + // MARK: - MoleculeViewProtocol - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.set(with: model, delegateObject, additionalData) - self.delegateObject = delegateObject + public func viewModelDidUpdate() { + boxes = viewModel.boxes + selectorModels = viewModel.selectorModels + FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) - guard let model = model as? RadioBoxesModel else { return } - boxes = model.boxes - FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) + } + + open func updateView(_ size: CGFloat) {} + + open override func didSelect(_ selectedControl: RadioBoxItem) { + super.didSelect(selectedControl) - backgroundColor = model.backgroundColor?.uiColor - - registerCells() - setHeight() - collectionView.reloadData() - } - - @objc override open func updateView(_ size: CGFloat) { - super.updateView(size) - self.size = size - itemSpacing = Padding.Component.gutterFor(size: size) - collectionView.updateView(size) - } - - // MARK: - Creation - - /// Creates the layout for the collection. - open func createCollectionViewLayout() -> UICollectionViewLayout { - let layout = UICollectionViewFlowLayout() - layout.scrollDirection = .vertical - layout.minimumLineSpacing = itemSpacing - layout.minimumInteritemSpacing = itemSpacing - return layout - } - - /// Creates the collection view. - open func createCollectionView() -> CollectionView { - let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout()) - collection.dataSource = self - collection.delegate = self - return collection - } - - /// Registers the cells with the collection view - open func registerCells() { - collectionView.register(RadioBoxCollectionViewCell.self, forCellWithReuseIdentifier: "RadioBoxCollectionViewCell") - } - - // MARK: - JSON Setters - open func setHeight() { - guard let boxes = boxes, boxes.count > 0 else { - collectionViewHeight.constant = 0 - return + // since the boxes has the state being tracked, we need to update the values here. + if let index = items.firstIndex(where: {$0 === selectedControl}), let selectedBox = boxes?[index] { + boxes?.forEach {$0.selected = false } + selectedBox.selected = true + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + radioDelegate?.selected(radioBox: selectedBox) } - - // Calculate the height - let rows = ceil(CGFloat(boxes.count) / numberOfColumns) - let height = (rows * boxHeight) + ((rows - 1) * itemSpacing) - collectionViewHeight?.constant = height - } -} - -extension RadioBoxes: UICollectionViewDelegateFlowLayout { - open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - let itemWidth: CGFloat = (collectionView.bounds.width - itemSpacing) / numberOfColumns - return CGSize(width: itemWidth, height: boxHeight) - } -} - -extension RadioBoxes: UICollectionViewDataSource { - open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return boxes?.count ?? 0 - } - - open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let molecule = boxes?[indexPath.row], - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioBoxCollectionViewCell", for: indexPath) as? RadioBoxCollectionViewCell else { - fatalError() - } - cell.reset() - cell.radioBox.isUserInteractionEnabled = false - - if let color = radioBoxesModel?.boxesColor { - cell.radioBox.backgroundColor = color.uiColor - } - if let color = radioBoxesModel?.selectedAccentColor { - cell.radioBox.accentColor = color.uiColor - } - - cell.set(with: molecule, delegateObject, nil) - cell.updateView(size ?? collectionView.bounds.width) - if molecule.selected { - collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically) - } - updateAccessibilityValue(collectionView: collectionView, cell: cell, indexPath: indexPath) - cell.layoutIfNeeded() - return cell - } -} - -extension RadioBoxes: UICollectionViewDelegate { - open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { - guard let molecule = boxes?[indexPath.row] else { return false } - return molecule.enabled - } - - open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return } - cell.radioBox.selectBox() - _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) - cell.updateAccessibility() - guard let radioBox = boxes?[indexPath.row] else { return } - radioDelegate?.selected(radioBox: radioBox) - } - - open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { - guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return } - cell.radioBox.deselectBox() - cell.updateAccessibility() } } From 8a89b2b2a917d9a34ff5396f1c5ac9a45fb94a0f Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 30 Jul 2024 08:22:24 -0500 Subject: [PATCH 3/7] updated methods and comments Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Selectors/RadioBox.swift | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift index ce890bc3..73b23f93 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift @@ -7,7 +7,7 @@ // import VDS -open class RadioBox: VDS.RadioBoxItem, VDSMoleculeViewProtocol, MFButtonProtocol { +@objcMembers open class RadioBox: VDS.RadioBoxItem, VDSMoleculeViewProtocol, MFButtonProtocol { //------------------------------------------------------ // MARK: - Properties //------------------------------------------------------ @@ -15,14 +15,18 @@ open class RadioBox: VDS.RadioBoxItem, VDSMoleculeViewProtocol, MFButtonProtocol open var delegateObject: MVMCoreUIDelegateObject? open var additionalData: [AnyHashable : Any]? - public var isOutOfStock: Bool { viewModel.strikethrough } + open var isOutOfStock: Bool { + get { strikethrough } + set { + strikethrough = newValue + viewModel?.strikethrough = newValue + } + } //-------------------------------------------------- - // MARK: - MVMCoreViewProtocol + // MARK: - Lifecycle //-------------------------------------------------- - open func updateView(_ size: CGFloat) {} - open override func setup() { super.setup() @@ -48,14 +52,23 @@ open class RadioBox: VDS.RadioBoxItem, VDSMoleculeViewProtocol, MFButtonProtocol } } + //-------------------------------------------------- + // MARK: - Functions + //-------------------------------------------------- + @objc open func selectBox() { - guard isEnabled, !isSelected else { return } - isSelected = true - viewModel.selected = isSelected + toggle() } @objc open func deselectBox() { - + toggle() } + + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + + open func updateView(_ size: CGFloat) {} + } From 192509feef0e32513926cd0d5b9621eb6f1114a9 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 30 Jul 2024 08:24:05 -0500 Subject: [PATCH 4/7] remvoed inverted since this is now in subclass Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index 105f9645..463afde3 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -16,8 +16,6 @@ import VDS public override static var identifier: String { "radioBoxes" } public var boxes: [RadioBoxModel] - public var inverted: Bool = false - public var surface: Surface { inverted ? .dark : .light } public var selectorModels: [VDS.RadioBoxGroup.RadioBoxItemModel] { boxes.compactMap({ item in @@ -58,7 +56,6 @@ import VDS private enum CodingKeys: String, CodingKey { case boxes - case inverted } //-------------------------------------------------- @@ -77,9 +74,6 @@ import VDS required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) boxes = try typeContainer.decode([RadioBoxModel].self, forKey: .boxes) - if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { - self.inverted = inverted - } try super.init(from: decoder) } @@ -87,6 +81,5 @@ import VDS try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(boxes, forKey: .boxes) - try container.encode(inverted, forKey: .inverted) } } From 8215542ee76716036560156b37e4cbef818bb898 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 30 Jul 2024 08:25:21 -0500 Subject: [PATCH 5/7] removed method not needed Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift index 73b23f93..815f2959 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift @@ -27,12 +27,6 @@ import VDS // MARK: - Lifecycle //-------------------------------------------------- - open override func setup() { - super.setup() - - addTarget(self, action: #selector(selectBox), for: .touchUpInside) - } - public func viewModelDidUpdate() { text = viewModel.text From 27718086743551597b1381d224c4a26667e40da3 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 30 Jul 2024 14:10:24 -0500 Subject: [PATCH 6/7] added inverted encoding Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift index 87326c7d..cd7623c2 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift @@ -105,5 +105,6 @@ import VDS try container.encode(strikethrough, forKey: .strikethrough) try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeModelIfPresent(action, forKey: .action) + try container.encode(inverted, forKey: .inverted) } } From 4b06a5ba1f2f63f974273f6bf1514a8203429995 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 30 Jul 2024 14:48:36 -0500 Subject: [PATCH 7/7] ensured inverted is set Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift index 7ba1f755..725cc893 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift @@ -53,6 +53,7 @@ open class RadioBoxes: VDS.RadioBoxGroup, VDSMoleculeViewProtocol { // MARK: - MoleculeViewProtocol public func viewModelDidUpdate() { boxes = viewModel.boxes + surface = viewModel.surface selectorModels = viewModel.selectorModels FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)