diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 03335a4d..df815789 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -173,8 +173,12 @@ AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; + BB2C969424331C46006FF80C /* RadioBoxes.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969324331C46006FF80C /* RadioBoxes.swift */; }; + BB2C969624331C74006FF80C /* RadioBoxesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969524331C74006FF80C /* RadioBoxesModel.swift */; }; + BB2C969824331F8E006FF80C /* RadioBoxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969724331F8E006FF80C /* RadioBoxModel.swift */; }; BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; }; BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */; }; + BB54C519243459280038326C /* RadioBoxCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C518243459280038326C /* RadioBoxCollectionViewCell.swift */; }; BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */; }; BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */; }; BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */; }; @@ -556,8 +560,12 @@ AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = ""; }; AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = ""; }; AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = ""; }; + BB2C969324331C46006FF80C /* RadioBoxes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioBoxes.swift; sourceTree = ""; }; + BB2C969524331C74006FF80C /* RadioBoxesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioBoxesModel.swift; sourceTree = ""; }; + BB2C969724331F8E006FF80C /* RadioBoxModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioBoxModel.swift; sourceTree = ""; }; BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = ""; }; BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsection.swift; sourceTree = ""; }; + BB54C518243459280038326C /* RadioBoxCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioBoxCollectionViewCell.swift; sourceTree = ""; }; BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTallModel.swift; sourceTree = ""; }; BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTall.swift; sourceTree = ""; }; BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerShort.swift; sourceTree = ""; }; @@ -1499,6 +1507,10 @@ D29DF17D21E69E26003B2FB9 /* Views */ = { isa = PBXGroup; children = ( + BB2C969324331C46006FF80C /* RadioBoxes.swift */, + BB54C518243459280038326C /* RadioBoxCollectionViewCell.swift */, + BB2C969524331C74006FF80C /* RadioBoxesModel.swift */, + BB2C969724331F8E006FF80C /* RadioBoxModel.swift */, 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */, 01509D922327ECFB00EF99AA /* ProgressBar.swift */, 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */, @@ -2079,8 +2091,10 @@ D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */, AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */, 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */, + BB2C969424331C46006FF80C /* RadioBoxes.swift in Sources */, 8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */, 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, + BB2C969624331C74006FF80C /* RadioBoxesModel.swift in Sources */, 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */, D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, 525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */, @@ -2132,6 +2146,7 @@ 011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, 011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */, + BB2C969824331F8E006FF80C /* RadioBoxModel.swift in Sources */, 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, 013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */, 525239C22407BD1000454969 /* ListTwoColumnPriceDetails.swift in Sources */, @@ -2160,6 +2175,7 @@ 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */, D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */, D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */, + BB54C519243459280038326C /* RadioBoxCollectionViewCell.swift in Sources */, D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */, 014AA72E23C5059B006F3E93 /* StackCenteredPageTemplateModel.swift in Sources */, D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxCollectionViewCell.swift b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxCollectionViewCell.swift new file mode 100644 index 00000000..532ff34f --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxCollectionViewCell.swift @@ -0,0 +1,87 @@ +// +// RadioBoxCollectionViewCell.swift +// MVMCoreUI +// +// Created by Dhamodaram Nandi on 01/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +open class RadioBoxCollectionViewCell: UICollectionViewCell, MoleculeViewProtocol { + + public let bodyLabel = Label.commonLabelB2(true) + public let lineView = View(frame: .zero) + + + var bottomView = MVMCoreUICommonViewsUtility.commonView() + + public var lineViewHeight: NSLayoutConstraint? + + + open override var isSelected: Bool{ + didSet{ + lineViewHeight?.constant = isSelected ? 4.0 : 0 + bottomView.layer.borderColor = isSelected ? UIColor.mfGet(forHex: "#0000").cgColor:UIColor.mfGet(forHex: "#747676").cgColor + + } + } + public override init(frame: CGRect) { + super.init(frame: .zero) + setupView() + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupView() + } + + public func setupView() { + guard bottomView.superview == nil else { + return + } + isAccessibilityElement = false + contentView.isAccessibilityElement = false + insetsLayoutMarginsFromSafeArea = false + contentView.insetsLayoutMarginsFromSafeArea = false + contentView.preservesSuperviewLayoutMargins = false + + contentView.addSubview(bottomView) + NSLayoutConstraint.constraintPinSubview(toSuperview: bottomView) + + lineView.translatesAutoresizingMaskIntoConstraints = false + bottomView.addSubview(lineView) + NSLayoutConstraint.constraintPinSubview(lineView, pinTop: true, pinBottom: false, pinLeft: true, pinRight: true) + lineViewHeight = lineView.heightAnchor.constraint(equalToConstant: 0) + lineViewHeight?.isActive = true + + + bodyLabel.translatesAutoresizingMaskIntoConstraints = false + bottomView.addSubview(bodyLabel) + NSLayoutConstraint.constraintPinSubview(bodyLabel, pinTop: false, topConstant:0 , pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 12, pinRight: true, rightConstant: 12) + bodyLabel.topAnchor.constraint(equalTo: lineView.bottomAnchor, constant: 12).isActive = true + bodyLabel.bottomAnchor.constraint(greaterThanOrEqualTo: bottomView.bottomAnchor, constant: -12.0).isActive = true + + bottomView.layer.borderWidth = 1.0 + bottomView.layer.borderColor = UIColor.mfGet(forHex: "#747676").cgColor + + + + } + + + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let collectionModel = model as? RadioBoxModel else { return } + + if let backgroundColor = collectionModel.backgroundColor { + self.bottomView.backgroundColor = backgroundColor.uiColor + } +// self.bottomView.backgroundColor = .red + lineView.backgroundColor = collectionModel.selectedAccentColor?.uiColor + bodyLabel.text = collectionModel.text + + + + } + + +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxModel.swift new file mode 100644 index 00000000..21adcb13 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxModel.swift @@ -0,0 +1,54 @@ +// +// RadioBoxModel.swift +// MVMCoreUI +// +// Created by Dhamodaram Nandi on 31/03/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +@objcMembers public class RadioBoxModel: MoleculeModelProtocol { + public static var identifier: String = "radioBox" + public var text: String + public var backgroundColor: Color? = Color(uiColor: .white) + public var selectedAccentColor: Color? = Color(uiColor: .red) + public var selected: Bool? = false + public var fieldValue: String? + + private enum CodingKeys: String, CodingKey { + case moleculeName + case text + case selectedAccentColor + case backgroundColor + case selected + case fieldValue + + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + text = try typeContainer.decode(String.self, forKey: .text) + + if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) { + selectedAccentColor = color + } + if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) { + backgroundColor = color + } + if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) { + selected = isSelected + } + fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) + + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(selectedAccentColor, forKey: .selectedAccentColor) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(selected, forKey: .selected) + try container.encodeIfPresent(fieldValue, forKey: .fieldValue) + + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxes.swift b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxes.swift new file mode 100644 index 00000000..9cc6ae5f --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxes.swift @@ -0,0 +1,122 @@ +// +// RadioBoxes.swift +// MVMCoreUI +// +// Created by Dhamodaram Nandi on 31/03/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +open class RadioBoxes: View { + + public let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) + + /// The models for the molecules. + var molecules: [MoleculeModelProtocol]? + + + /// The height of the carousel. Default is 300. + public var collectionViewHeight: NSLayoutConstraint? + + public var delegateObject: MVMCoreUIDelegateObject? + + + + // MARK: - MVMCoreViewProtocol + open override func setupView() { + super.setupView() + guard collectionView.superview == nil else { + return + } + collectionView.translatesAutoresizingMaskIntoConstraints = false + collectionView.dataSource = self + collectionView.delegate = self + collectionView.showsHorizontalScrollIndicator = false + collectionView.backgroundColor = .clear + collectionView.isAccessibilityElement = false + addSubview(collectionView) + + collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 300) + collectionViewHeight?.isActive = true + NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView) + + } + + + + // MARK: - MoleculeViewProtocol + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + self.delegateObject = delegateObject + super.set(with: model, delegateObject, additionalData) + guard let radioBoxesModel = model as? RadioBoxesModel else { return } + backgroundColor = .white + + registerCells() + setupLayout(with: radioBoxesModel) + prepareMolecules(with: radioBoxesModel) + collectionView.reloadData() + } + + // MARK: - JSON Setters + /// Updates the layout being used + + func setupLayout(with carouselModel: RadioBoxesModel?) { + let layout = UICollectionViewFlowLayout() + layout.scrollDirection = .vertical + layout.minimumLineSpacing = 10 + layout.minimumInteritemSpacing = 10 + collectionView.collectionViewLayout = layout + } + + func prepareMolecules(with radioBoxesModel: RadioBoxesModel?) { + guard let newMolecules = radioBoxesModel?.boxes else { + molecules = nil + return + } + molecules = newMolecules + collectionView.reloadData() + + } + + + /// Registers the cells with the collection view + func registerCells() { + + collectionView.register(RadioBoxCollectionViewCell.self, forCellWithReuseIdentifier: "RadioBoxCollectionViewCell") + } + + + // MARK: - Convenience + /// Returns the (identifier, class) of the molecule for the given map. + func getMoleculeInfo(with molecule: MoleculeModelProtocol, delegateObject: MVMCoreUIDelegateObject?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? { + guard let className = MoleculeObjectMapping.shared()?.getMoleculeClass(molecule) else { + return nil + } + return (className.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName, className, molecule) + } + + +} +extension RadioBoxes: UICollectionViewDelegateFlowLayout { + open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + let itemWidth = (collectionView.bounds.width - 30)/2 + return CGSize(width: itemWidth, height: 64) + } + + +} + +extension RadioBoxes: UICollectionViewDataSource { + open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return molecules?.count ?? 0 + } + + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let molecule = molecules?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioBoxCollectionViewCell", for: indexPath) as? RadioBoxCollectionViewCell else { + return UICollectionViewCell() + } + cell.set(with: molecule, delegateObject, nil) + (cell as? MVMCoreViewProtocol)?.updateView(collectionView.bounds.width) + return cell + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxesModel.swift new file mode 100644 index 00000000..80425bde --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxesModel.swift @@ -0,0 +1,57 @@ +// +// RadioBoxesModel.swift +// MVMCoreUI +// +// Created by Dhamodaram Nandi on 31/03/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +@objcMembers public class RadioBoxesModel: MoleculeModelProtocol { + public static var identifier: String = "radioBoxes" + public var backgroundColor: Color? = Color(uiColor: .white) + public var selectedAccentColor: Color? = Color(uiColor: .red) + public var enabled: Bool? = true + public var boxes: [RadioBoxModel] + public var fieldKey: String? + public var groupName: String? + + private enum CodingKeys: String, CodingKey { + case moleculeName + case selectedAccentColor + case backgroundColor + case enabled + case boxes + case fieldKey + case groupName + + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) { + selectedAccentColor = color + } + if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) { + backgroundColor = color + } + if let isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { + enabled = isEnabled + } + boxes = try typeContainer.decode([RadioBoxModel].self, forKey: .boxes) + fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) + + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(selectedAccentColor, forKey: .selectedAccentColor) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(enabled, forKey: .enabled) + try container.encodeIfPresent(fieldKey, forKey: .fieldKey) + try container.encodeIfPresent(groupName, forKey: .groupName) + + } +} diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index bfa6db01..f0ea8a63 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -67,6 +67,8 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: DateDropdownEntryField.self, viewModelClass: DateDropdownEntryFieldModel.self) // Other Atoms + MoleculeObjectMapping.shared()?.register(viewClass: RadioBoxes.self, viewModelClass: RadioBoxesModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self) MoleculeObjectMapping.shared()?.register(viewClass: MultiProgress.self, viewModelClass: MultiProgressBarModel.self) MoleculeObjectMapping.shared()?.register(viewClass: CaretView.self, viewModelClass: CaretViewModel.self)