From 7471d2adf68375bf6a97cd948d5e20ff4f196342 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 17 Apr 2020 19:05:01 -0400 Subject: [PATCH] Separate radio swatch model file remove item from radio swatch name add in reset function to be consistent. Fix selected color issues with outer circle Center line Move height calculations to be dynamic minor encoding updates --- MVMCoreUI.xcodeproj/project.pbxproj | 20 +++--- ...adioSwatchItem.swift => RadioSwatch.swift} | 46 +++++++------ ...ft => RadioSwatchCollectionViewCell.swift} | 8 +-- .../Atoms/Selectors/RadioSwatchModel.swift | 64 ++++++++++++++++++ .../Atoms/Selectors/RadioSwatches.swift | 36 +++++----- .../Atoms/Selectors/RadioSwatchesModel.swift | 67 ++----------------- 6 files changed, 130 insertions(+), 111 deletions(-) rename MVMCoreUI/Atomic/Atoms/Selectors/{RadioSwatchItem.swift => RadioSwatch.swift} (77%) rename MVMCoreUI/Atomic/Atoms/Selectors/{RadioSwatchItemCollectionViewCell.swift => RadioSwatchCollectionViewCell.swift} (71%) create mode 100644 MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 077b0ca2..befe232c 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -190,11 +190,11 @@ AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; }; AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; }; AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; }; - AA85236C244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */; }; + AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; }; - AAB9C10A243496DD00151545 /* RadioSwatchItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatchItem.swift */; }; + AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatch.swift */; }; AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; }; BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; }; BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; }; @@ -226,6 +226,7 @@ C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; }; D202AFE4242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */; }; D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */; }; + D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092348244A51D40044AD09 /* RadioSwatchModel.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; @@ -620,11 +621,11 @@ AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = ""; }; AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = ""; }; AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = ""; }; - AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchItemCollectionViewCell.swift; sourceTree = ""; }; + AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.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 = ""; }; AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = ""; }; - AAB9C109243496DD00151545 /* RadioSwatchItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchItem.swift; sourceTree = ""; }; + AAB9C109243496DD00151545 /* RadioSwatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatch.swift; sourceTree = ""; }; AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = ""; }; BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinksModel.swift; sourceTree = ""; }; BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinks.swift; sourceTree = ""; }; @@ -656,6 +657,7 @@ C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = ""; }; D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextAlignment+Extension.swift"; sourceTree = ""; }; D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionViewScrollPosition+Extension.swift"; sourceTree = ""; }; + D2092348244A51D40044AD09 /* RadioSwatchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchModel.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; @@ -1439,8 +1441,9 @@ 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, AAB9C10724346F4B00151545 /* RadioSwatches.swift */, - AAB9C109243496DD00151545 /* RadioSwatchItem.swift */, - AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */, + D2092348244A51D40044AD09 /* RadioSwatchModel.swift */, + AAB9C109243496DD00151545 /* RadioSwatch.swift */, + AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */, ); path = Selectors; sourceTree = ""; @@ -2114,7 +2117,7 @@ 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */, D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */, - AAB9C10A243496DD00151545 /* RadioSwatchItem.swift in Sources */, + AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, 011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */, D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */, @@ -2219,6 +2222,7 @@ D260105D23D0BCD400764D80 /* Stack.swift in Sources */, 0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */, BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */, + D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */, 8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, 01EB368F23609801006832FA /* LabelModel.swift in Sources */, @@ -2333,7 +2337,7 @@ 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */, AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */, D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */, - AA85236C244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift in Sources */, + AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */, 52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */, D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */, 0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift similarity index 77% rename from MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift rename to MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift index a6e6b802..35294457 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift @@ -1,5 +1,5 @@ // -// RadioSwatchItem.swift +// RadioSwatch.swift // MVMCoreUI // // Created by Lekshmi S on 01/04/20. @@ -9,21 +9,19 @@ import Foundation import UIKit -open class RadioSwatchItem: Control { +open class RadioSwatch: Control { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- public let bottomText = Label.createLabelRegularMicro(true) - public var isOutOfStock = false - public var fillColor: Color = Color(uiColor: .mvmBlue) private var circleLayer: CAShapeLayer? private var selectedLayer: CALayer? private var strikeLayer: CALayer? private var maskLayer: CALayer? - public var radioSwatchModel: RadioSwatchItemModel? { - return model as? RadioSwatchItemModel + public var radioSwatchModel: RadioSwatchModel? { + return model as? RadioSwatchModel } //-------------------------------------------------- @@ -40,18 +38,23 @@ open class RadioSwatchItem: Control { addSubview(bottomText) bottomText.textAlignment = .center - NSLayoutConstraint.constraintPinSubview(bottomText, pinTop: true, topConstant: 38, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0) + NSLayoutConstraint.constraintPinSubview(bottomText, pinTop: true, topConstant: 38, pinBottom: true, bottomConstant: 0, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0) addTarget(self, action: #selector(selectSwatch), for: .touchUpInside) } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - guard let model = model as? RadioSwatchItemModel else { return } - fillColor = model.color - isSelected = model.selected ?? false - isEnabled = model.enabled ?? true + guard let model = model as? RadioSwatchModel else { return } + isSelected = model.selected + isEnabled = model.enabled bottomText.text = model.text - isOutOfStock = model.strikethrough ?? false + } + + public override func reset() { + super.reset() + isSelected = false + isEnabled = true + bottomText.text = nil } //------------------------------------------------------ @@ -60,14 +63,14 @@ open class RadioSwatchItem: Control { open override func draw(_ layer: CALayer, in ctx: CGContext) { //Draw the swatch circleLayer?.removeFromSuperlayer() - let circle = getCircle(color: .mvmBlack, thickness: 1) + let circle = getCircle(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1) layer.addSublayer(circle) circleLayer = circle //Draw the strikethrough strikeLayer?.removeFromSuperlayer() - if isOutOfStock { - let line = getStrikeThrough(color: .mvmBlack, thickness: 1) + if radioSwatchModel?.strikethrough ?? false { + let line = getStrikeThrough(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1) layer.addSublayer(line) strikeLayer = line } @@ -75,12 +78,11 @@ open class RadioSwatchItem: Control { //Draw the selected layer selectedLayer?.removeFromSuperlayer() if isSelected { - let outerCircle = getSelectedLayer(color: .mvmBlack, thickness: 1) + let outerCircle = getSelectedLayer(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1) layer.addSublayer(outerCircle) selectedLayer = outerCircle bottomText.isHidden = false } else { - circleLayer?.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath bottomText.isHidden = true } @@ -115,10 +117,10 @@ open class RadioSwatchItem: Control { func getCircle(color: UIColor, thickness: CGFloat) -> CAShapeLayer { let circle = CAShapeLayer() circle.name = "innercircle" - circle.fillColor = fillColor.cgColor + circle.fillColor = radioSwatchModel?.color.cgColor ?? UIColor.blue.cgColor circle.opacity = 1.0 circle.lineWidth = thickness - circle.strokeColor = isSelected ? color.cgColor : UIColor.mvmCoolGray6.cgColor + circle.strokeColor = color.cgColor let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)) circle.path = circlePath.cgPath @@ -131,11 +133,11 @@ open class RadioSwatchItem: Control { strikeThrough.fillColor = nil strikeThrough.opacity = 1.0 strikeThrough.lineWidth = thickness - strikeThrough.strokeColor = isSelected ? color.cgColor : UIColor.mvmCoolGray6.cgColor + strikeThrough.strokeColor = color.cgColor let linePath = UIBezierPath() - linePath.move(to: CGPoint(x: 12, y: 30)) - linePath.addLine(to: CGPoint(x: 42, y: 0)) + linePath.move(to: CGPoint(x: 12, y: 31)) + linePath.addLine(to: CGPoint(x: 42, y: 1)) strikeThrough.path = linePath.cgPath return strikeThrough } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchCollectionViewCell.swift similarity index 71% rename from MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift rename to MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchCollectionViewCell.swift index a820a680..8412dab2 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchCollectionViewCell.swift @@ -1,5 +1,5 @@ // -// RadioSwatchItemCollectionViewCell.swift +// RadioSwatchCollectionViewCell.swift // MVMCoreUI // // Created by Lekshmi S on 13/04/20. @@ -7,8 +7,8 @@ // import Foundation -open class RadioSwatchItemCollectionViewCell: CollectionViewCell { - public let radioSwatch = RadioSwatchItem() +open class RadioSwatchCollectionViewCell: CollectionViewCell { + public let radioSwatch = RadioSwatch() open override func setupView() { super.setupView() @@ -17,7 +17,7 @@ open class RadioSwatchItemCollectionViewCell: CollectionViewCell { } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let model = model as? RadioSwatchItemModel else { return } + guard let model = model as? RadioSwatchModel else { return } radioSwatch.set(with: model, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift new file mode 100644 index 00000000..3aadd467 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift @@ -0,0 +1,64 @@ +// +// RadioSwatchModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/17/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class RadioSwatchModel: MoleculeModelProtocol { + public static var identifier: String = "radioSwatch" + public var backgroundColor: Color? + public var color: Color = Color(uiColor: .mvmBlue) + public var text: String? + public var selected: Bool = false + public var enabled: Bool = true + public var strikethrough: Bool = false + public var fieldValue: String? + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case color + case text + case selected + case enabled + case strikethrough + case fieldValue + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) { + self.color = color + } + text = try typeContainer.decodeIfPresent(String.self, forKey: .text) + if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) { + self.selected = selected + } + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { + self.enabled = enabled + } + if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) { + self.strikethrough = strikethrough + } + 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.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encode(color, forKey: .color) + try container.encodeIfPresent(text, forKey: .text) + try container.encode(selected, forKey: .selected) + try container.encode(enabled, forKey: .enabled) + try container.encode(strikethrough, forKey: .strikethrough) + try container.encodeIfPresent(fieldValue, forKey: .fieldValue) + } +} + + diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift index f13dd331..8a6b8faf 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift @@ -13,7 +13,7 @@ open class RadioSwatches: View { // MARK: - Properties //-------------------------------------------------- public var collectionView: CollectionView! - public var swatches: [RadioSwatchItemModel]? + public var swatches: [RadioSwatchModel]? private var size: CGFloat? private var delegateObject: MVMCoreUIDelegateObject? @@ -30,6 +30,7 @@ open class RadioSwatches: View { open override func layoutSubviews() { super.layoutSubviews() // Accounts for any collection size changes + setHeight() DispatchQueue.main.async { self.collectionView.collectionViewLayout.invalidateLayout() } @@ -57,24 +58,18 @@ open class RadioSwatches: View { guard let radioSwatchesModel = model as? RadioSwatchesModel else { return } swatches = radioSwatchesModel.swatches FormValidator.setupValidation(for: radioSwatchesModel, delegate: delegateObject?.formHolderDelegate) - registerCells() - setHeight() collectionView.reloadData() } //------------------------------------------------------ // MARK: - Methods //------------------------------------------------------ - /// Registers the cells with the collection view - open func registerCells() { - collectionView.register(RadioSwatchItemCollectionViewCell.self, forCellWithReuseIdentifier: "RadioSwatchItemCollectionViewCell") - } - /// Creates the collection view. open func createCollectionView() -> CollectionView { let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout()) collection.dataSource = self collection.delegate = self + collection.register(RadioSwatchCollectionViewCell.self, forCellWithReuseIdentifier: "RadioSwatchCollectionViewCell") return collection } @@ -93,10 +88,17 @@ open class RadioSwatches: View { return } // Calculate the height - let collectionViewWidth = UIScreen.main.bounds.width - (2 * MFStyler.defaultHorizontalPaddingForApplicationWidth()) - let swatchesInRow = floor(CGFloat(collectionViewWidth/(cellSize + itemSpacing))) + let swatchesInRow = floor(CGFloat(collectionView.bounds.width/(cellSize + itemSpacing))) let numberOfRows = ceil(CGFloat(swatches.count)/swatchesInRow) let height = (numberOfRows * cellSize) + (itemSpacing * (numberOfRows-1)) + + if let oldHeight = collectionViewHeight?.constant, + height != oldHeight { + // Notify delegate of height change, called async to avoid various race conditions caused while happening while laying out initially. + DispatchQueue.main.async { + self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) + } + } collectionViewHeight?.constant = CGFloat(height) } } @@ -116,13 +118,14 @@ extension RadioSwatches: UICollectionViewDataSource { } open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchItemCollectionViewCell", for: indexPath) as? RadioSwatchItemCollectionViewCell else { + guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchCollectionViewCell", for: indexPath) as? RadioSwatchCollectionViewCell else { fatalError() } + cell.reset() cell.radioSwatch.isUserInteractionEnabled = false cell.set(with: molecule, delegateObject, nil) cell.updateView(size ?? collectionView.bounds.width) - if molecule.selected ?? false { + if molecule.selected { collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically) } cell.layoutIfNeeded() @@ -132,17 +135,18 @@ extension RadioSwatches: UICollectionViewDataSource { extension RadioSwatches: UICollectionViewDelegate { open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { - guard let molecule = swatches?[indexPath.row] else {return true } - return molecule.enabled ?? true + guard let molecule = swatches?[indexPath.row] else { return false } + return molecule.enabled } open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return } + guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return } cell.radioSwatch.selectSwatch() _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) } + open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { - guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return } + guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return } cell.radioSwatch.deselectSwatch() } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift index d422d0db..db8e5d5d 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift @@ -9,9 +9,9 @@ import Foundation @objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol { - public var backgroundColor: Color? public static var identifier: String = "radioSwatches" - public var swatches: [RadioSwatchItemModel] + public var backgroundColor: Color? + public var swatches: [RadioSwatchModel] public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName public var baseValue: AnyHashable? @@ -19,7 +19,7 @@ import Foundation /// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch. public func formFieldValue() -> AnyHashable? { let selectedSwatch = swatches.first { (swatch) -> Bool in - return (swatch.selected ?? false) + return swatch.selected } return selectedSwatch?.fieldValue ?? selectedSwatch?.text } @@ -34,8 +34,8 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - self.backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - self.swatches = try typeContainer.decode([RadioSwatchItemModel].self, forKey: .swatches) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + swatches = try typeContainer.decode([RadioSwatchModel].self, forKey: .swatches) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { self.groupName = groupName @@ -49,61 +49,6 @@ import Foundation try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(swatches, forKey: .swatches) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) - try container.encodeIfPresent(groupName, forKey: .groupName) + try container.encode(groupName, forKey: .groupName) } } - -@objcMembers public class RadioSwatchItemModel: MoleculeModelProtocol { - public var backgroundColor: Color? - public static var identifier: String = "radioSwatchItem" - public var color: Color = Color(uiColor: .mvmBlue) - public var text: String? - public var selected: Bool? = false - public var enabled: Bool? = true - public var strikethrough: Bool? = false - public var fieldValue: String? - - private enum CodingKeys: String, CodingKey { - case moleculeName - case backgroundColor - case color - case text - case selected - case enabled - case strikethrough - case fieldValue - } - - required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - color = try typeContainer.decode(Color.self, forKey: .color) - if let text = try typeContainer.decodeIfPresent(String.self, forKey: .text) { - self.text = text - } - if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) { - self.selected = selected - } - if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { - self.enabled = enabled - } - if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) { - self.strikethrough = strikethrough - } - 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.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encode(color, forKey: .color) - try container.encodeIfPresent(text, forKey: .text) - try container.encodeIfPresent(selected, forKey: .selected) - try container.encodeIfPresent(enabled, forKey: .enabled) - try container.encodeIfPresent(strikethrough, forKey: .strikethrough) - try container.encodeIfPresent(fieldValue, forKey: .fieldValue) - } -} - -