From 77476e13550545a3f00ed3e90665ea0f56a9c715 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 18 Feb 2020 14:31:26 +0530 Subject: [PATCH 01/48] 19162- List - Four Column - Data Usage - Divider story initial commit. Added molecule class, model class. --- MVMCoreUI.xcodeproj/project.pbxproj | 16 +++++ .../ListFourColumnDataUsageDivider.swift | 72 +++++++++++++++++++ .../ListFourColumnDataUsageDividerModel.swift | 59 +++++++++++++++ .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 4 files changed, 148 insertions(+) create mode 100644 MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift create mode 100644 MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 03743382..1b43f48b 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -128,6 +128,8 @@ 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; }; 94FB966223D797DA003D482B /* MFTextButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94FB966023D797DA003D482B /* MFTextButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94FB966323D797DA003D482B /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94FB966123D797DA003D482B /* MFTextButton.m */; }; + AA84562723FBB4A80013B068 /* ListFourColumnDataUsageDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA84562623FBB4A80013B068 /* ListFourColumnDataUsageDivider.swift */; }; + AA84562923FBB4C00013B068 /* ListFourColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA84562823FBB4C00013B068 /* ListFourColumnDataUsageDividerModel.swift */; }; C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; }; C07065C42395677300FBF997 /* Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07065C32395677300FBF997 /* Link.swift */; }; C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */; }; @@ -451,6 +453,8 @@ 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; sourceTree = ""; }; 94FB966023D797DA003D482B /* MFTextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextButton.h; sourceTree = ""; }; 94FB966123D797DA003D482B /* MFTextButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextButton.m; sourceTree = ""; }; + AA84562623FBB4A80013B068 /* ListFourColumnDataUsageDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageDivider.swift; sourceTree = ""; }; + AA84562823FBB4C00013B068 /* ListFourColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageDividerModel.swift; sourceTree = ""; }; C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; C07065C32395677300FBF997 /* Link.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Link.swift; sourceTree = ""; }; C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedListModel.swift; sourceTree = ""; }; @@ -782,6 +786,15 @@ name = "Recovered References"; sourceTree = ""; }; + AA84562523FBB4770013B068 /* FourColumn */ = { + isa = PBXGroup; + children = ( + AA84562623FBB4A80013B068 /* ListFourColumnDataUsageDivider.swift */, + AA84562823FBB4C00013B068 /* ListFourColumnDataUsageDividerModel.swift */, + ); + path = FourColumn; + sourceTree = ""; + }; D213347423842FE3008E41B3 /* Controllers */ = { isa = PBXGroup; children = ( @@ -980,6 +993,7 @@ D22B38EC23F4E10700490EF6 /* SectionDividers */ = { isa = PBXGroup; children = ( + AA84562523FBB4770013B068 /* FourColumn */, D22B38ED23F4E11100490EF6 /* ThreeColumn */, ); path = SectionDividers; @@ -1630,6 +1644,7 @@ D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, D2B18B7F2360913400A9AEDC /* Control.swift in Sources */, + AA84562723FBB4A80013B068 /* ListFourColumnDataUsageDivider.swift in Sources */, 0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */, D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */, 012A88C8238DB02000FE3DA1 /* ModelMoleculeDelegateProtocol.swift in Sources */, @@ -1828,6 +1843,7 @@ 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */, D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */, D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */, + AA84562923FBB4C00013B068 /* ListFourColumnDataUsageDividerModel.swift in Sources */, 014AA72E23C5059B006F3E93 /* StackCenteredPageTemplateModel.swift in Sources */, D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */, D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */, diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift new file mode 100644 index 00000000..6fc99c94 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift @@ -0,0 +1,72 @@ +// +// ListFourColumnDataUsageDivider.swift +// MVMCoreUI +// +// Created by Lekshmi S on 18/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class ListFourColumnDataUsageDivider: TableViewCell { + + //------------------------------------------------------- + // MARK: - Outlets + //------------------------------------------------------- + let label1 = Label.commonLabelB1(true) + let label2 = Label.commonLabelB1(true) + let label3 = Label.commonLabelB1(true) + let label4 = Label.commonLabelB1(true) + let stack = Stack(frame: .zero) + + //------------------------------------------------------- + // MARK: - View Lifecycle + //------------------------------------------------------- + open override func updateView(_ size: CGFloat) { + super.updateView(size) + stack.updateView(size) + } + + open override func setupView() { + super.setupView() + stack.translatesAutoresizingMaskIntoConstraints = false + stack.stackItems = [StackItem(andContain: label1), StackItem(andContain: label2), StackItem(andContain: label3), StackItem(andContain: label4)] + contentView.addSubview(stack) + containerHelper.constrainView(stack) + } + + //------------------------------------------------------ + // MARK: - Molecule + //------------------------------------------------------ + open override func reset() { + super.reset() + stack.reset() + } + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? ListFourColumnDataUsageDividerModel else { return } + label1.setWithModel(model.label1, delegateObject, additionalData) + label2.setWithModel(model.label2, delegateObject, additionalData) + label3.setWithModel(model.label3, delegateObject, additionalData) + label4.setWithModel(model.label4, delegateObject, additionalData) + + //Create a stack model to use for the internal stack and set the alignment of labels + let label1 = StackItemModel(percent: 20) + label1.horizontalAlignment = .leading + let label2 = StackItemModel(percent: 40) + label2.horizontalAlignment = .leading + let label3 = StackItemModel(percent: 20) + label3.horizontalAlignment = .leading + let label4 = StackItemModel(percent: 20) + label4.horizontalAlignment = .leading + let stackModel = StackModel(molecules: [label1, label2, label3, label4]) + stackModel.axis = .horizontal + stack.model = stackModel + stack.restack() + } + + public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 90 + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift new file mode 100644 index 00000000..1277f4bb --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift @@ -0,0 +1,59 @@ +// +// ListFourColumnDataUsageDividerModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 18/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListFourColumnDataUsageDividerModel: ListItemModel, MoleculeModelProtocol { + public static var identifier: String = "list4CDiv" + public var label1: LabelModel + public var label2: LabelModel + public var label3: LabelModel + public var label4: LabelModel + + public init(label1: LabelModel, label2: LabelModel, label3: LabelModel, label4: LabelModel) { + self.label1 = label1 + self.label2 = label2 + self.label3 = label3 + self.label4 = label4 + super.init() + setDefaults() + } + + // Defaults to set + override public func setDefaults() { + super.setDefaults() + style = "tallDivider" + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case label1 + case label2 + case label3 + case label4 + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + label1 = try typeContainer.decode(LabelModel.self, forKey: .label1) + label2 = try typeContainer.decode(LabelModel.self, forKey: .label2) + label3 = try typeContainer.decode(LabelModel.self, forKey: .label3) + label4 = try typeContainer.decode(LabelModel.self, forKey: .label4) + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(label1, forKey: .label1) + try container.encode(label2, forKey: .label2) + try container.encode(label3, forKey: .label3) + try container.encode(label4, forKey: .label4) + } +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index a04f964a..48ca49ee 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -55,6 +55,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) // Vertical Combination Molecules From 43a809aba01ba461506b4925f856ce08ed177eb2 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 18 Feb 2020 16:33:28 +0530 Subject: [PATCH 02/48] Modified code as labels are optional. --- .../ListFourColumnDataUsageDividerModel.swift | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift index 1277f4bb..e07ca87f 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift @@ -10,10 +10,10 @@ import Foundation public class ListFourColumnDataUsageDividerModel: ListItemModel, MoleculeModelProtocol { public static var identifier: String = "list4CDiv" - public var label1: LabelModel - public var label2: LabelModel - public var label3: LabelModel - public var label4: LabelModel + public var label1: LabelModel? + public var label2: LabelModel? + public var label3: LabelModel? + public var label4: LabelModel? public init(label1: LabelModel, label2: LabelModel, label3: LabelModel, label4: LabelModel) { self.label1 = label1 @@ -40,20 +40,20 @@ public class ListFourColumnDataUsageDividerModel: ListItemModel, MoleculeModelPr required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - label1 = try typeContainer.decode(LabelModel.self, forKey: .label1) - label2 = try typeContainer.decode(LabelModel.self, forKey: .label2) - label3 = try typeContainer.decode(LabelModel.self, forKey: .label3) - label4 = try typeContainer.decode(LabelModel.self, forKey: .label4) + label1 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .label1) + label2 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .label2) + label3 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .label3) + label4 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .label4) try super.init(from: decoder) } public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(label1, forKey: .label1) - try container.encode(label2, forKey: .label2) - try container.encode(label3, forKey: .label3) - try container.encode(label4, forKey: .label4) + try container.encodeIfPresent(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(label1, forKey: .label1) + try container.encodeIfPresent(label2, forKey: .label2) + try container.encodeIfPresent(label3, forKey: .label3) + try container.encodeIfPresent(label4, forKey: .label4) } } From 7d8f850e638c18ab9cf30d4eb9a08692c911713e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 20 Feb 2020 14:35:35 -0500 Subject: [PATCH 03/48] providing new molecule --- MVMCoreUI.xcodeproj/project.pbxproj | 20 ++++- .../Atoms/Buttons/Link/ExternalLink.swift | 73 +++++++++++++++++++ .../Buttons/Link/ExternalLinkModel.swift | 16 ++++ MVMCoreUI/Atoms/Buttons/{ => Link}/Link.swift | 2 + .../Atoms/Buttons/{ => Link}/LinkModel.swift | 4 +- .../Buttons/MFCustomButton+ActionModel.swift | 2 + ...maryButton+MoleculeProtocolExtension.swift | 7 +- .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 8 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift create mode 100644 MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift rename MVMCoreUI/Atoms/Buttons/{ => Link}/Link.swift (99%) rename MVMCoreUI/Atoms/Buttons/{ => Link}/LinkModel.swift (97%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 281a0672..480d2219 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -94,6 +94,8 @@ 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; }; 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; }; 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; }; + 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BAE23FEF956004C5109 /* ExternalLink.swift */; }; + 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */; }; 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; }; 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; }; 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; }; @@ -420,6 +422,8 @@ 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = ""; }; 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = ""; }; 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = ""; }; + 0AE98BAE23FEF956004C5109 /* ExternalLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalLink.swift; sourceTree = ""; }; + 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalLinkModel.swift; sourceTree = ""; }; 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = ""; }; 31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = ""; }; 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = ""; }; @@ -755,6 +759,17 @@ path = Views; sourceTree = ""; }; + 0AE98BAD23FEF92B004C5109 /* Link */ = { + isa = PBXGroup; + children = ( + D28A838823CCCFCB00DFE4FC /* LinkModel.swift */, + C07065C32395677300FBF997 /* Link.swift */, + 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */, + 0AE98BAE23FEF956004C5109 /* ExternalLink.swift */, + ); + path = Link; + sourceTree = ""; + }; 946EE1B5237B663A0036751F /* Extensions */ = { isa = PBXGroup; children = ( @@ -1239,12 +1254,11 @@ D29DF16821E69E1F003B2FB9 /* Buttons */ = { isa = PBXGroup; children = ( + 0AE98BAD23FEF92B004C5109 /* Link */, 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */, DBC4391A224421A0001AB423 /* CaretLink.swift */, D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */, D2E2A99E23E07F8A000B42E6 /* PillButton.swift */, - D28A838823CCCFCB00DFE4FC /* LinkModel.swift */, - C07065C32395677300FBF997 /* Link.swift */, D28A838C23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift */, D28A837623C79FC600DFE4FC /* MFCustomButton+ActionModel.swift */, ); @@ -1679,6 +1693,7 @@ C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */, + 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */, 012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */, D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, @@ -1780,6 +1795,7 @@ 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */, D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, + 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, 0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */, D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift new file mode 100644 index 00000000..3f0aa5d6 --- /dev/null +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift @@ -0,0 +1,73 @@ +// +// ExternalLink.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 2/20/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + + +open class ExternalLink: Link { + //-------------------------------------------------- + // MARK: - ModelMoleculeViewProtocol + //-------------------------------------------------- + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + + guard let model = model as? ExternalLinkModel else { return } + + } +} + +// MARK: - MVMCoreViewProtocol +extension ExternalLink { + + public override func updateView(_ size: CGFloat) { + super.updateView(size) + } + + public override func setupView() { + super.setupView() + + let imageView = UIImageView(image: MVMCoreUIUtility.imageNamed("externalLink")) + imageView.contentMode = .scaleAspectFit + imageView.translatesAutoresizingMaskIntoConstraints = false + + addSubview(imageView) + + imageView.heightAnchor.constraint(equalToConstant: round(0.8 * titleLabel!.font.pointSize)).isActive = true + imageView.widthAnchor.constraint(equalToConstant: round(0.8 * titleLabel!.font.pointSize)).isActive = true + + imageView.leadingAnchor.constraint(equalTo: titleLabel!.trailingAnchor, constant: PaddingOne).isActive = true + trailingAnchor.constraint(greaterThanOrEqualTo: imageView.trailingAnchor).isActive = true + + imageView.bottomAnchor.constraint(equalTo: titleLabel!.lastBaselineAnchor).isActive = true + } +} + +/* + static func getTextAttachmentFrom(url: String, dimension: CGFloat, label: Label) -> NSTextAttachment { + + let dimension = round(dimension * 0.8) + + let imageAttachment = NSTextAttachment() + imageAttachment.bounds = CGRect(x: 0, y: 0, width: dimension, height: dimension) + + DispatchQueue.global(qos: .default).async { + + guard let url = URL(string: url), + let data = try? Data(contentsOf: url) + else { return } + + DispatchQueue.main.sync { + imageAttachment.image = UIImage(data: data) + label.setNeedsDisplay() + } + } + + return imageAttachment + } + */ diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift new file mode 100644 index 00000000..a7fc5211 --- /dev/null +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift @@ -0,0 +1,16 @@ +// +// ExternalLinkModel.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 2/20/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +class ExternalLinkModel: LinkModel { + + override public class var identifier: String { + return "externalLink" + } +} diff --git a/MVMCoreUI/Atoms/Buttons/Link.swift b/MVMCoreUI/Atoms/Buttons/Link/Link.swift similarity index 99% rename from MVMCoreUI/Atoms/Buttons/Link.swift rename to MVMCoreUI/Atoms/Buttons/Link/Link.swift index 5dbbed16..a0e2583c 100644 --- a/MVMCoreUI/Atoms/Buttons/Link.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/Link.swift @@ -42,7 +42,9 @@ import UIKit public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? LinkModel else { return } + setTitle(model.title, for: .normal) setTitleColor(model.textColor.uiColor, for: .normal) setTitleColor(model.disabledColor.uiColor, for: .disabled) diff --git a/MVMCoreUI/Atoms/Buttons/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift similarity index 97% rename from MVMCoreUI/Atoms/Buttons/LinkModel.swift rename to MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift index 7094a038..5a58decd 100644 --- a/MVMCoreUI/Atoms/Buttons/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift @@ -13,7 +13,9 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { // MARK: - Properties //-------------------------------------------------- - public static var identifier: String = "link" + public class var identifier: String { + return "link" + } public var backgroundColor: Color? public var title: String diff --git a/MVMCoreUI/Atoms/Buttons/MFCustomButton+ActionModel.swift b/MVMCoreUI/Atoms/Buttons/MFCustomButton+ActionModel.swift index d008a7fb..84f4be33 100644 --- a/MVMCoreUI/Atoms/Buttons/MFCustomButton+ActionModel.swift +++ b/MVMCoreUI/Atoms/Buttons/MFCustomButton+ActionModel.swift @@ -9,7 +9,9 @@ import Foundation public extension MFCustomButton { + func set(with action: ActionModelProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + buttonDelegate = delegateObject?.buttonDelegate add({ [weak self] sender in guard let self = self else { return } diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift index 39b015ae..62b16927 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift @@ -10,8 +10,11 @@ import Foundation // temporary until link is finished extension PrimaryButton: ModelMoleculeViewProtocol { - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + + public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let model = model as? ButtonModel else { return } + setTitle(model.title, for: .normal) backgroundColor = model.backgroundColor?.uiColor @@ -23,7 +26,6 @@ extension PrimaryButton: ModelMoleculeViewProtocol { FormValidator.setupValidation(molecule: selfForm, delegate: delegateObject?.formValidationProtocol) } - if let style = model.style { switch style { case .primary: @@ -32,6 +34,7 @@ extension PrimaryButton: ModelMoleculeViewProtocol { setAsSecondaryCustom() } } + if let size = model.size { switch size { case .standard: diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index ac7375d7..329347b1 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -29,6 +29,7 @@ import Foundation // Buttons MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TwoButtonView.self, viewModelClass: TwoButtonViewModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ExternalLink.self, viewModelClass: ExternalLinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Link.self, viewModelClass: LinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretLink.self, viewModelClass: CaretLinkModel.self) From b96b48787c97d2f4ba66462d92126354a4d67b52 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 20 Feb 2020 14:49:25 -0500 Subject: [PATCH 04/48] beginning arrow molecule --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++++ MVMCoreUI/Atoms/Views/Arrow.swift | 21 ++++++++++ MVMCoreUI/Atoms/Views/ArrowModel.swift | 54 ++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 MVMCoreUI/Atoms/Views/Arrow.swift create mode 100644 MVMCoreUI/Atoms/Views/ArrowModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 281a0672..a9f666c3 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -94,6 +94,8 @@ 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; }; 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; }; 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; }; + 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; }; + 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; }; 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; }; 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; }; 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; }; @@ -420,6 +422,8 @@ 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = ""; }; 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = ""; }; 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = ""; }; + 0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = ""; }; + 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = ""; }; 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = ""; }; 31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = ""; }; 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = ""; }; @@ -1283,6 +1287,8 @@ 0AA33B392398524F0067DD0F /* Toggle.swift */, D260105423CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift */, 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */, + 0AE98BB423FF18D2004C5109 /* Arrow.swift */, + 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */, ); path = Views; sourceTree = ""; @@ -1785,6 +1791,7 @@ D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */, D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */, + 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */, 017BEB4223620AD20024EF95 /* FormModelProtocol.swift in Sources */, 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, @@ -1808,6 +1815,7 @@ 01EB369323609801006832FA /* HeaderModel.swift in Sources */, D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, 0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */, + 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */, D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */, 012A88C6238DA34000FE3DA1 /* ModuleMoleculeModel.swift in Sources */, 94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Views/Arrow.swift b/MVMCoreUI/Atoms/Views/Arrow.swift new file mode 100644 index 00000000..f2e98abb --- /dev/null +++ b/MVMCoreUI/Atoms/Views/Arrow.swift @@ -0,0 +1,21 @@ +// +// Arrow.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 2/20/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +class Arrow: View { + + /* + // Only override draw() if you perform custom drawing. + // An empty implementation adversely affects performance during animation. + override func draw(_ rect: CGRect) { + // Drawing code + } + */ + +} diff --git a/MVMCoreUI/Atoms/Views/ArrowModel.swift b/MVMCoreUI/Atoms/Views/ArrowModel.swift new file mode 100644 index 00000000..00e85cfb --- /dev/null +++ b/MVMCoreUI/Atoms/Views/ArrowModel.swift @@ -0,0 +1,54 @@ +// +// ArrowModel.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 2/20/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class ArrowModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public static var identifier: String = "arrow" + public var backgroundColor: Color? + + public var color: Color = Color(uiColor: .mfLighterGray()) + public var direction: Bool? + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case color + case direction + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) { + self.color = color + } + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + direction = try typeContainer.decodeIfPresent(Bool.self, forKey: .direction) + + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(color, forKey: .color) + try container.encode(direction, forKey: .direction) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + } +} From 4ad4eb7f469226d9be57a1cb4604c2dfd856b086 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Tue, 25 Feb 2020 11:49:26 -0500 Subject: [PATCH 05/48] add new font --- MVMCoreUI.xcodeproj/project.pbxproj | 28 ++++++++------- .../Containers/NavigationController.swift | 6 ++-- .../Fonts/NHaasGroteskDSStd-45Lt.otf | Bin 62664 -> 0 bytes .../Fonts/NHaasGroteskDSStd-55Rg.otf | Bin 75048 -> 0 bytes .../Fonts/NHaasGroteskDSStd-75Bd.otf | Bin 64188 -> 0 bytes .../Fonts/VerizonNHGeDS-Bold.otf | Bin 0 -> 54172 bytes .../Fonts/VerizonNHGeDS-Regular.otf | Bin 0 -> 50284 bytes .../Fonts/VerizonNHGeTX-Bold.otf | Bin 0 -> 55316 bytes .../Fonts/VerizonNHGeTX-Regular.otf | Bin 0 -> 53776 bytes MVMCoreUI/Utility/MFFonts.h | 6 ++-- MVMCoreUI/Utility/MFFonts.m | 34 ++++++++++++++---- 11 files changed, 49 insertions(+), 25 deletions(-) delete mode 100644 MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-45Lt.otf delete mode 100644 MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-55Rg.otf delete mode 100644 MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-75Bd.otf create mode 100755 MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeDS-Bold.otf create mode 100755 MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeDS-Regular.otf create mode 100755 MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeTX-Bold.otf create mode 100755 MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeTX-Regular.otf diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 3e9138f7..cb821240 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -126,6 +126,10 @@ 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */; }; 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */; }; 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */; }; + 94CA227C24058534002D6750 /* VerizonNHGeTX-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */; }; + 94CA227D24058534002D6750 /* VerizonNHGeDS-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */; }; + 94CA227E24058534002D6750 /* VerizonNHGeDS-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */; }; + 94CA227F24058534002D6750 /* VerizonNHGeTX-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */; }; 94F217B623E0BF6100A47C06 /* PrimaryButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = 94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; }; 94FB966223D797DA003D482B /* MFTextButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94FB966023D797DA003D482B /* MFTextButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -288,10 +292,7 @@ D29DF2E121E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2E021E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF2EE21ECEADF003B2FB9 /* MFFonts.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF14D21E693AD003B2FB9 /* MFFonts.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF14C21E693AD003B2FB9 /* MFFonts.m */; }; - D29DF31A21ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31621ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf */; }; D29DF31B21ECECC0003B2FB9 /* OCRAExtended.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */; }; - D29DF31C21ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31821ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf */; }; - D29DF31D21ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31921ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf */; }; D29DF32021ED0CBA003B2FB9 /* LabelView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF31E21ED0CBA003B2FB9 /* LabelView.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF31F21ED0CBA003B2FB9 /* LabelView.m */; }; D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF32221ED0DA2003B2FB9 /* TextButtonView.m */; }; @@ -457,6 +458,10 @@ 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeColorModel.swift; sourceTree = ""; }; 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeImageModel.swift; sourceTree = ""; }; 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeActionModel.swift; sourceTree = ""; }; + 94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Bold.otf"; sourceTree = ""; }; + 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeDS-Regular.otf"; sourceTree = ""; }; + 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeDS-Bold.otf"; sourceTree = ""; }; + 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Regular.otf"; sourceTree = ""; }; 94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrimaryButtonView.h; sourceTree = ""; }; 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; sourceTree = ""; }; 94FB966023D797DA003D482B /* MFTextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextButton.h; sourceTree = ""; }; @@ -631,10 +636,7 @@ D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFLoadingViewController.h; sourceTree = ""; }; D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFLoadingViewController.m; sourceTree = ""; }; D29DF2E021E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPanelProtocol.h; sourceTree = ""; }; - D29DF31621ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-45Lt.otf"; sourceTree = ""; }; D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = OCRAExtended.ttf; sourceTree = ""; }; - D29DF31821ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-75Bd.otf"; sourceTree = ""; }; - D29DF31921ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-55Rg.otf"; sourceTree = ""; }; D29DF31E21ED0CBA003B2FB9 /* LabelView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelView.h; sourceTree = ""; }; D29DF31F21ED0CBA003B2FB9 /* LabelView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LabelView.m; sourceTree = ""; }; D29DF32221ED0DA2003B2FB9 /* TextButtonView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextButtonView.m; sourceTree = ""; }; @@ -1410,10 +1412,11 @@ D29DF31521ECECC0003B2FB9 /* Fonts */ = { isa = PBXGroup; children = ( - D29DF31621ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf */, + 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */, + 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */, + 94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */, + 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */, D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */, - D29DF31821ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf */, - D29DF31921ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf */, ); path = Fonts; sourceTree = ""; @@ -1613,14 +1616,15 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 94CA227F24058534002D6750 /* VerizonNHGeTX-Regular.otf in Resources */, D29DF2AF21E7B3A4003B2FB9 /* MFTextView.xib in Resources */, - D29DF31C21ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf in Resources */, - D29DF31D21ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf in Resources */, 0A21DB8E235E06EF00C160A2 /* MFDigitTextField.xib in Resources */, + 94CA227C24058534002D6750 /* VerizonNHGeTX-Bold.otf in Resources */, D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */, 0A21DB86235E06EF00C160A2 /* MFTextField.xib in Resources */, - D29DF31A21ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf in Resources */, + 94CA227D24058534002D6750 /* VerizonNHGeDS-Regular.otf in Resources */, D29DF32E21EE8C3D003B2FB9 /* Media.xcassets in Resources */, + 94CA227E24058534002D6750 /* VerizonNHGeDS-Bold.otf in Resources */, D29DF31B21ECECC0003B2FB9 /* OCRAExtended.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 623b2f47..e10f09c5 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -20,9 +20,9 @@ import UIKit navigationBar.shadowImage = UIImage() navigationBar.isOpaque = true navigationBar.tintColor = .black - if let font = MFFonts.mfFont75Bd(MFSizeObject(standardSize: 14, standardiPadPortraitSize: 16, iPadProLandscapeSize: 18)?.getValueBasedOnScreenSize() ?? 14) { - navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font]; - } + let font = MFFonts.mfFont75Bd(MFSizeObject(standardSize: 14, standardiPadPortraitSize: 16, iPadProLandscapeSize: 18)?.getValueBasedOnScreenSize() ?? 14) + + navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font]; } public static func setupNavigationController() -> Self? { diff --git a/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-45Lt.otf b/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-45Lt.otf deleted file mode 100644 index bddef9eb7e16ee3c6d72d91ee3ad064ad5d15b43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62664 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�=> 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

jan8MpnGKFv7c}Nl?0Cx%b?Ma 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 F{{T=I5EuXe diff --git a/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-55Rg.otf b/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-55Rg.otf deleted file mode 100644 index f56ed7aaf89f16bad53d72034e0002639d48364e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75048 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

_D2qW`Ep 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

3x1o+N6#i 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�p+^D*}?d&IQRY`36#If$`3Wb_t9AUr? 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 N4tK2zzhVXQ{{W43)8_yH literal 0 HcmV?d00001 diff --git a/MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeDS-Regular.otf b/MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeDS-Regular.otf new file mode 100755 index 0000000000000000000000000000000000000000..ce34c5964033809a6a7565f6baae1dc41a8c102f GIT binary patch literal 50284 zcmeFYcU)7+_cwlTF1a_}XjEccO}t6K0)kTQVnq=|v0y2*JC92OgnStoHOUnyl2vH(4c-) zEh?R2sQ%tQKKkUd-ft+Xp-53fvU&vi^$PY|@iRs3ETpJL>wER+=|dlE=UD~bOEmqtk@5if??JhqqDfVX`dsRKFQm5DM~Y!y zLJoDWp~Do*v)PBhKLh^k#@aJmAk9z`k_-Q!4O9N7D@AcHp*(=Kw{WtSSu4a+RDX(w zZ^}lZqnA)pN+y{n34*l0^+}JSJZMjflE_&b3HfIOWt^pP^;h410sV+x{`gb!@=qUH z!IV?CplCTMrvH%S!b4BV;oF|h{Hy}py@Imw1q(>16jvKiGh&y0}mtfu9ZOHHPluK68Zi;b=6UY)P_ zF2Bxqa@HksddJ15B}7GzG3j^fJ>1;e>HEgT#+lOMje5TrLu6EJq~0$!%thZVI$Ce3 zmZ(oKCK?lxjo~gsj0sT_;$rmyzPFj0mdYw-q&DA)b~n=GZ_=d>7x?$2E8f45N?byB#hI?Mf?x48)C!t zF@`jKs1an3j7l^a6O7^ds91fNF~MYj=h&o#sKoH7FcS!n=<=@$@E!wIOi_kdePGy_ z6hne(LJwnNRAekL3Qg1hXDR5?tyN1dPT93@8vgAu7TY8D&fa^BJRB=!sgOPAn)TIm*HaG7`Sy>T8TnHkzWs z45a@)QPpnItrzJ#IV#x@t&jUQvaqHk4Ui@v@_3#&Cqn1Oi$mW&6L5v_k!;@>54 z(fdVw<7$Xa(~nOAKPK@9+Qvd)ime`C!q>1%2Aeo0E-9K!(&Q*(ip4?xT~>%2M)0|C zYb+r{`>Fz~m|+mdAbKRk>SN--OV`a+FZ_%lJRc*+PlepC!)fZ9=zA8AR)Qel(}P~E6# z_~^gmmS{;CsYGa*KqbR>IMf_sNkvf;EWGtp0Od>df|^FE2Ng&Sgl8m`1e^@e#vSUr zSw0;>mVQvTA1pTh&cWK=+PdXG+W)=gKl{@EYwbiB8yU6!uipR8<^R-Q07#z%e|i{` z0X{?nyI}2#}d* zgy_IJ`;3rkVHt(hTdaJDjmTJ%q4b+X)*2-L-(>Z*F{|q8oVs z*Kw0RlA$(<5pn-&voOeyfe(@8>n!}XA_pPbcF^fu|AXIO(6rMoO$@L|Rh%Eeijq_gbyr9cq!8WQ|WG#t^HK zK3#yL2|n>u2g(&bDVC25jPmah+y%x$#%`5>#3wS&SZJvSUc_Tf(30qtcoeY&iBnep ziiceC#<0pjM*rVNE8>B~_T-z4{VNAD$4E~G=syB_jfOv>S*vA?7WqgWt4Hf8N6RS4 z`{wIBB>or;79lUw zVfD2bi_}&vkaaJI%{YoDYat2F;7 z`w*Y8N43ZwNc#@Z>i_R;Lx4gHs>#5!9znD$PaEbbJk#OB!jl60cMA0By(TZ3CN{m{u=2e`{1e;!G4zi= z|NOIB0zI{fcBi|61Ow^OAi-pi;0j1^?>h;U`Ud(&dc8#g4}E)!1SWm@cM=5J4YylT zEkRw7py6KoI)!*|_Er-vC2(<$m<$A=ydo#0sq{(g8UulTtF(A)=k zsqQ$LADCv9q+vB?I*D#af1*DFu=|-d!}oW8)?Udsl>H(3ic){e z{u@PGFm9*|&#yF4fRg|7A6-5MIu$&32K74~NPVC^==#(%x*@Hl)wGTtME9Y?>Auu*x+b9S zf6@W;7`i|0M&(iYbO`N5`%^FJQ0gYNg04lCQg^5_>IEeO^q!@7z@}>e-mU;_+?G

y76(UbB4{Jj?hI)B(I4~C^{ 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 literal 0 HcmV?d00001 diff --git a/MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeTX-Bold.otf b/MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeTX-Bold.otf new file mode 100755 index 0000000000000000000000000000000000000000..59b1f438744b24d3f81258a69e52fac419e39a86 GIT binary patch literal 55316 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 MLDurIPMCxIKZ(ilegFUf literal 0 HcmV?d00001 diff --git a/MVMCoreUI/Utility/MFFonts.h b/MVMCoreUI/Utility/MFFonts.h index 484e2c82..28e502c6 100644 --- a/MVMCoreUI/Utility/MFFonts.h +++ b/MVMCoreUI/Utility/MFFonts.h @@ -12,9 +12,9 @@ @interface MFFonts : NSObject -+ (nullable UIFont *)mfFont75Bd:(CGFloat)size; -+ (nullable UIFont *)mfFont55Rg:(CGFloat)size; ++ (nonnull UIFont *)mfFont75Bd:(CGFloat)size; ++ (nonnull UIFont *)mfFont55Rg:(CGFloat)size; + (nullable UIFont *)mfFontOcratxt:(CGFloat)size; -+ (nullable UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size; ++ (nonnull UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size; @end diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 65326e6c..264dcf18 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -11,13 +11,21 @@ #import "MVMCoreUIUtility.h" @import MVMCore.MVMCoreLoggingHandler; +static NSString * const DSBold = @"VerizonNHGeDS-Bold"; +static NSString * const DSRegular = @"VerizonNHGeDS-Regular"; +static NSString * const TXBold = @"VerizonNHGeTX-Bold"; +static NSString * const TXRegular = @"VerizonNHGeTX-Regular"; + + @implementation MFFonts + (void)loadMVMFonts { static dispatch_once_t once; dispatch_once(&once, ^{ - [MFFonts loadFont:@"NHaasGroteskDSStd-75Bd" type:@"otf"]; - [MFFonts loadFont:@"NHaasGroteskDSStd-55Rg" type:@"otf"]; + [MFFonts loadFont:DSBold type:@"otf"]; + [MFFonts loadFont:DSRegular type:@"otf"]; + [MFFonts loadFont:TXBold type:@"otf"]; + [MFFonts loadFont:TXRegular type:@"otf"]; [MFFonts loadFont:@"OCRAExtended" type:@"ttf"]; }); } @@ -39,14 +47,26 @@ CFRelease(provider); } -+ (nullable UIFont *)mfFont75Bd:(CGFloat)size { ++ (UIFont *)mfFont75Bd:(CGFloat)size { [self loadMVMFonts]; - return [UIFont fontWithName:@"NHaasGroteskDSStd-75Bd" size:size]; + UIFont *font; + if (size >= 15) { + font = [UIFont fontWithName:DSBold size:size]; + } else { + font = [UIFont fontWithName:TXBold size:size]; + } + return font ?: [UIFont boldSystemFontOfSize:size]; } -+ (nullable UIFont *)mfFont55Rg:(CGFloat)size { ++ (UIFont *)mfFont55Rg:(CGFloat)size { [self loadMVMFonts]; - return [UIFont fontWithName:@"NHaasGroteskDSStd-55Rg" size:size]; + UIFont *font; + if (size >= 15) { + font = [UIFont fontWithName:DSRegular size:size]; + } else { + font = [UIFont fontWithName:TXRegular size:size]; + } + return font ?: [UIFont systemFontOfSize:size]; } + (nullable UIFont *)mfFontOcratxt:(CGFloat)size { @@ -54,7 +74,7 @@ return [UIFont fontWithName:@"OCRAExtended" size:size]; } -+ (nullable UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size { ++ (UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size { return [UIFont fontWithName:name size:size] ?: [self mfFont55Rg:size]; } From 455507626cda24a3c6021d62e5082dd6baf7d206 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Tue, 25 Feb 2020 13:59:24 -0500 Subject: [PATCH 06/48] add new fonts method, change font from nullable to non null for better swift typing --- MVMCoreUI/Atoms/Views/Label/Label.swift | 145 +++++++++ MVMCoreUI/Styles/MFStyler.h | 120 ++++++- MVMCoreUI/Styles/MFStyler.m | 402 +++++++++++++++++++++++- MVMCoreUI/Utility/MFFonts.h | 9 + MVMCoreUI/Utility/MFFonts.m | 25 +- 5 files changed, 695 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index f08d532d..5e11e116 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -132,6 +132,89 @@ public typealias ActionBlock = () -> () // MARK: - Factory Functions //------------------------------------------------------ + /// Title 2XLarge + @objc public static func commonLabelTitle2XLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleTitle2XLarge(scale) + return label + } + + /// TitleXLarge + @objc public static func commonLabelTitleXLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleTitleXLarge(scale) + return label + } + + /// BoldTitleLarge + @objc public static func commonLabelBoldTitleLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleBoldTitleLarge(scale) + return label + } + + /// RegularTitleLarge + @objc public static func commonLabelRegularTitleLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleRegularTitleLarge(scale) + return label + } + + /// BoldTitleMedium + @objc public static func commonLabelBoldTitleMedium(_ scale: Bool) -> Label { + let label = Label.label() + label.styleBoldTitleMedium(scale) + return label + } + + /// RegularTitleMedium + @objc public static func commonLabelRegularTitleMedium(_ scale: Bool) -> Label { + let label = Label.label() + label.styleRegularTitleMedium(scale) + return label + } + + /// BoldBodyLarge + @objc public static func commonLabelBoldBodyLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleBoldBodyLarge(scale) + return label + } + + /// RegularBodyLarge + @objc public static func commonLabelRegularBodyLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleRegularBodyLarge(scale) + return label + } + + /// BoldBodySmall + @objc public static func commonLabelBoldBodySmall(_ scale: Bool) -> Label { + let label = Label.label() + label.styleBoldBodySmall(scale) + return label + } + + /// RegularBodySmall + @objc public static func commonLabelRegularBodySmall(_ scale: Bool) -> Label { + let label = Label.label() + label.styleRegularBodySmall(scale) + return label + } + /// BoldMicro + @objc public static func commonLabelBoldMicro(_ scale: Bool) -> Label { + let label = Label.label() + label.styleBoldMicro(scale) + return label + } + /// RegularMicro + @objc public static func commonLabelRegularMicro(_ scale: Bool) -> Label { + let label = Label.label() + label.styleRegularMicro(scale) + return label + } + + //2.0 fonts init methods /// H1 -> HeadlineLarge @objc public static func commonLabelH1(_ scale: Bool) -> Label { let label = Label.label() @@ -481,6 +564,68 @@ public typealias ActionBlock = () -> () // MARK: - Methods //------------------------------------------------------ + //mva 3.0 font + @objc public func styleTitle2XLarge(_ scale: Bool) { + MFStyler.styleLabelTitle2XLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleTitleXLarge(_ scale: Bool) { + MFStyler.styleLabelTitleXLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleBoldTitleLarge(_ scale: Bool) { + MFStyler.styleLabelBoldTitleLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleRegularTitleLarge(_ scale: Bool) { + MFStyler.styleLabelRegularTitleLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleBoldTitleMedium(_ scale: Bool) { + MFStyler.styleLabelBoldTitleMedium(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleRegularTitleMedium(_ scale: Bool) { + MFStyler.styleLabelRegularTitleMedium(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleBoldBodyLarge(_ scale: Bool) { + MFStyler.styleLabelBoldBodyLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleRegularBodyLarge(_ scale: Bool) { + MFStyler.styleLabelRegularBodyLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleBoldBodySmall(_ scale: Bool) { + MFStyler.styleLabelBoldBodySmall(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleRegularBodySmall(_ scale: Bool) { + MFStyler.styleLabelRegularBodySmall(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleBoldMicro(_ scale: Bool) { + MFStyler.styleLabelBoldMicro(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleRegularMicro(_ scale: Bool) { + MFStyler.styleLabelRegularMicro(self, genericScaling: false) + setScale(scale) + } + + //2.0 fonts @objc public func styleH1(_ scale: Bool) { MFStyler.styleLabelH1(self, genericScaling: false) setScale(scale) diff --git a/MVMCoreUI/Styles/MFStyler.h b/MVMCoreUI/Styles/MFStyler.h index bdef57ba..eb89312c 100644 --- a/MVMCoreUI/Styles/MFStyler.h +++ b/MVMCoreUI/Styles/MFStyler.h @@ -98,6 +98,46 @@ B3 -> Legal //------------------------------------------------- // Returns the fonts for these styles. Scales them as needed by default + +#pragma mark - 3.0 fonts +///Bold 36pt ++ (nonnull UIFont *)fontTitle2XLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontTitle2XLarge; +///Bold 32pt ++ (nonnull UIFont *)fontTitleXLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontTitleXLarge; +///Bold 24pt ++ (nonnull UIFont *)fontBoldTitleLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontBoldTitleLarge; +///Regular 24pt ++ (nonnull UIFont *)fontRegularTitleLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontRegularTitleLarge; +///Bold 20pt ++ (nonnull UIFont *)fontBoldTitleMedium:(BOOL)genericScaling; ++ (nonnull UIFont *)fontBoldTitleMedium; +///Regular 20pt ++ (nonnull UIFont *)fontRegularTitleMedium:(BOOL)genericScaling; ++ (nonnull UIFont *)fontRegularTitleMedium; +///Bold 16pt ++ (nonnull UIFont *)fontBoldBodyLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontBoldBodyLarge; +///Regular 16pt ++ (nonnull UIFont *)fontRegularBodyLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontRegularBodyLarge; +///Bold 13pt ++ (nonnull UIFont *)fontBoldBodySmall:(BOOL)genericScaling; ++ (nonnull UIFont *)fontBoldBodySmall; +///Regular 13pt ++ (nonnull UIFont *)fontRegularBodySmall:(BOOL)genericScaling; ++ (nonnull UIFont *)fontRegularBodySmall; +///Bold 11pt ++ (nonnull UIFont *)fontBoldMicro:(BOOL)genericScaling; ++ (nonnull UIFont *)fontBoldMicro; +///Regular 11pt ++ (nonnull UIFont *)fontRegularMicro:(BOOL)genericScaling; ++ (nonnull UIFont *)fontRegularMicro; + + #pragma mark - 2.0 fonts //75Bd 40pt @@ -206,9 +246,50 @@ B3 -> Legal //------------------------------------------------- // Applies the styles to the passed in objects. +#pragma mark - 3.0 Styles + ++ (void)styleLabelTitle2XLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelTitle2XLarge:(nonnull UILabel *)label; + ++ (void)styleLabelTitleXLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelTitleXLarge:(nonnull UILabel *)label; + ++ (void)styleLabelBoldTitleLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelBoldTitleLarge:(nonnull UILabel *)label; + ++ (void)styleLabelRegularTitleLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelRegularTitleLarge:(nonnull UILabel *)label; + ++ (void)styleLabelBoldTitleMedium:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelBoldTitleMedium:(nonnull UILabel *)label; + ++ (void)styleLabelRegularTitleMedium:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelRegularTitleMedium:(nonnull UILabel *)label; + ++ (void)styleLabelBoldBodyLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelBoldBodyLarge:(nonnull UILabel *)label; + ++ (void)styleLabelRegularBodyLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelRegularBodyLarge:(nonnull UILabel *)label; + ++ (void)styleLabelBoldBodySmall:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelBoldBodySmall:(nonnull UILabel *)label; + ++ (void)styleLabelRegularBodySmall:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelRegularBodySmall:(nonnull UILabel *)label; + ++ (void)styleLabelBoldMicro:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelBoldMicro:(nonnull UILabel *)label; + ++ (void)styleLabelRegularMicro:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelRegularMicro:(nonnull UILabel *)label; + +/// Will style the label with mva 3.0 fonts based on the string. ++ (BOOL)styleMVA3Label:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling; + #pragma mark - 2.0 styles -/// Will style the label based on the string. Accepted values, H1, H2, H3, H32, B1, B2, B3, B20 +/// Will style the label based on the string. Accepted values, including mva3.0 fonts and 2.0 fonts H1, H2, H3, H32, B1, B2, B3, B20 + (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style; + (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling; @@ -257,6 +338,43 @@ B3 -> Legal #pragma mark - Attributed Strings ++ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetTitleXLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetTitleXLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetBoldTitleLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetBoldTitleLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetRegularTitleLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetRegularTitleLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetBoldTitleMediumAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetBoldTitleMediumAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetRegularTitleMediumAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetRegularTitleMediumAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetBoldBodyLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetBoldBodyLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetRegularBodyLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetRegularBodyLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetBoldBodySmallAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetBoldBodySmallAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetRegularBodySmallAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetRegularBodySmallAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetBoldMicroAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetBoldMicroAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetRegularMicroAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetRegularMicroAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + + /// Will style the string based on the string. Accepted values, H1, H2, H3, H32, B1, B2, B3, B20 + (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style; + (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling; diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index c3dc8946..69a04b3e 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -111,6 +111,152 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; }]; } +#pragma mark - 3.0 fonts + ++ (nonnull UIFont *)fontTitle2XLarge:(BOOL)genericScaling { + CGFloat size = 36; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontTitle2XLarge { + return [self fontTitle2XLarge:YES]; +} + ++ (nonnull UIFont *)fontTitleXLarge:(BOOL)genericScaling { + CGFloat size = 32; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} ++ (nonnull UIFont *)fontTitleXLarge{ + return [self fontTitleXLarge:YES]; +} + ++ (nonnull UIFont *)fontBoldTitleLarge:(BOOL)genericScaling { + CGFloat size = 24; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontBoldTitleLarge { + return [self fontBoldTitleLarge:YES]; +} + ++ (nonnull UIFont *)fontRegularTitleLarge:(BOOL)genericScaling { + CGFloat size = 24; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont55Rg:size]; +} + ++ (nonnull UIFont *)fontRegularTitleLarge { + return [self fontRegularTitleLarge:YES]; +} + ++ (nonnull UIFont *)fontBoldTitleMedium:(BOOL)genericScaling { + CGFloat size = 20; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontBoldTitleMedium { + return [self fontBoldTitleMedium:YES]; +} + ++ (nonnull UIFont *)fontRegularTitleMedium:(BOOL)genericScaling { + CGFloat size = 20; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont55Rg:size]; +} + ++ (nonnull UIFont *)fontRegularTitleMedium { + return [self fontRegularTitleMedium:YES]; +} + ++ (nonnull UIFont *)fontBoldBodyLarge:(BOOL)genericScaling { + CGFloat size = 16; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontBoldBodyLarge { + return [self fontBoldBodyLarge:YES]; +} + ++ (nonnull UIFont *)fontRegularBodyLarge:(BOOL)genericScaling { + CGFloat size = 16; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont55Rg:size]; +} + ++ (nonnull UIFont *)fontRegularBodyLarge { + return [self fontRegularBodyLarge:YES]; +} + ++ (nonnull UIFont *)fontBoldBodySmall:(BOOL)genericScaling { + CGFloat size = 13; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontBoldBodySmall { + return [self fontBoldBodySmall:YES]; +} + ++ (nonnull UIFont *)fontRegularBodySmall:(BOOL)genericScaling { + CGFloat size = 13; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont55Rg:size]; +} + ++ (nonnull UIFont *)fontRegularBodySmall { + return [self fontRegularBodySmall:YES]; +} + ++ (nonnull UIFont *)fontBoldMicro:(BOOL)genericScaling { + CGFloat size = 11; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontBoldMicro { + return [self fontBoldMicro:YES]; +} + ++ (nonnull UIFont *)fontRegularMicro:(BOOL)genericScaling { + CGFloat size = 11; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont55Rg:size]; +} + ++ (nonnull UIFont *)fontRegularMicro { + return [self fontRegularMicro:YES]; +} + + #pragma mark - 2.0 fonts + (nullable UIFont *)fontH1:(BOOL)genericScaling { @@ -514,10 +660,165 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; return [MFFonts mfFont55Rg:[self sizeFontGenericForCurrentDevice:size]]; } +#pragma mark - 3.0 Styles + ++ (void)styleLabelTitle2XLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontTitle2XLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelTitle2XLarge:(nonnull UILabel *)label { + [self styleLabelTitle2XLarge:label genericScaling:YES]; +} + ++ (void)styleLabelTitleXLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontTitleXLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelTitleXLarge:(nonnull UILabel *)label { + [self styleLabelTitleXLarge:label genericScaling:YES]; +} + ++ (void)styleLabelBoldTitleLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontBoldTitleLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelBoldTitleLarge:(nonnull UILabel *)label { + [self styleLabelBoldTitleLarge:label genericScaling:YES]; +} + ++ (void)styleLabelRegularTitleLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontRegularTitleLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelRegularTitleLarge:(nonnull UILabel *)label { + [self styleLabelBoldTitleLarge:label genericScaling:YES]; +} + ++ (void)styleLabelBoldTitleMedium:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontBoldTitleMedium:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelBoldTitleMedium:(nonnull UILabel *)label { + [self styleLabelBoldTitleMedium:label genericScaling:YES]; +} + ++ (void)styleLabelRegularTitleMedium:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontRegularTitleMedium:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelRegularTitleMedium:(nonnull UILabel *)label { + [self styleLabelRegularTitleMedium:label genericScaling:YES]; +} + ++ (void)styleLabelBoldBodyLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontBoldBodyLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelBoldBodyLarge:(nonnull UILabel *)label { + [self styleLabelBoldBodyLarge:label genericScaling:YES]; +} + ++ (void)styleLabelRegularBodyLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontRegularBodyLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelRegularBodyLarge:(nonnull UILabel *)label { + [self styleLabelRegularBodyLarge:label genericScaling:YES]; +} + ++ (void)styleLabelBoldBodySmall:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontBoldBodySmall:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelBoldBodySmall:(nonnull UILabel *)label { + [self styleLabelBoldBodySmall:label genericScaling:YES]; +} + ++ (void)styleLabelRegularBodySmall:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontRegularBodySmall:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelRegularBodySmall:(nonnull UILabel *)label { + [self styleLabelRegularBodySmall:label genericScaling:YES]; +} + ++ (void)styleLabelBoldMicro:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontBoldMicro:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelBoldMicro:(nonnull UILabel *)label { + [self styleLabelBoldMicro:label genericScaling:YES]; +} + ++ (void)styleLabelRegularMicro:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontRegularMicro:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelRegularMicro:(nonnull UILabel *)label { + [self styleLabelRegularMicro:label genericScaling:YES]; +} + ++ (BOOL)styleMVA3Label:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling { + if ([style isEqualToString:@"Title2XLarge"]) { + [self styleLabelTitle2XLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"TitleXLarge"]) { + [self styleLabelTitleXLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"BoldTitleLarge"]) { + [self styleLabelBoldTitleLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"RegularTitleLarge"]) { + [self styleLabelRegularTitleLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"BoldTitleMedium"]) { + [self styleLabelBoldTitleMedium:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"RegularTitleMedium"]) { + [self styleLabelRegularTitleMedium:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"BoldBodyLarge"]) { + [self styleLabelBoldBodyLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"RegularBodyLarge"]) { + [self styleLabelRegularBodyLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"BoldBodySmall"]) { + [self styleLabelBoldBodySmall:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"RegularBodySmall"]) { + [self styleLabelRegularBodySmall:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"BoldMicro"]) { + [self styleLabelBoldMicro:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"RegularMicro"]) { + [self styleLabelRegularMicro:label genericScaling:genericScaling]; + return YES; + } else { + return NO; + } +} + + #pragma mark - 2.0 Styles + (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling { - if ([style isEqualToString:@"H1"]) { + if ([self styleMVA3Label:label withStyle:style genericScaling:genericScaling]) { + //try mva 3.0 font first + } else if ([style isEqualToString:@"H1"]) { [self styleLabelH1:label genericScaling:genericScaling]; } else if ([style isEqualToString:@"H2"]) { [self styleLabelH2:label genericScaling:genericScaling]; @@ -697,6 +998,105 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; return attributedString; } + ++ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetTitle2XLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontTitle2XLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetTitleXLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetTitleXLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetTitleXLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontTitleXLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetBoldTitleLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetBoldTitleLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetBoldTitleLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontBoldTitleLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetRegularTitleLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetRegularTitleLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetRegularTitleLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontRegularTitleLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetBoldTitleMediumAttributedString:(nullable NSString *)string { + return [MFStyler styleGetBoldTitleMediumAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetBoldTitleMediumAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontBoldTitleMedium:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetRegularTitleMediumAttributedString:(nullable NSString *)string { + return [MFStyler styleGetRegularTitleMediumAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetRegularTitleMediumAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontRegularTitleMedium:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetBoldBodyLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetBoldBodyLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetBoldBodyLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontBoldBodyLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetRegularBodyLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetRegularBodyLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetRegularBodyLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontRegularBodyLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetBoldBodySmallAttributedString:(nullable NSString *)string { + return [MFStyler styleGetBoldBodySmallAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetBoldBodySmallAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontBoldBodySmall:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetRegularBodySmallAttributedString:(nullable NSString *)string { + return [MFStyler styleGetRegularBodySmallAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetRegularBodySmallAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontRegularBodySmall:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetBoldMicroAttributedString:(nullable NSString *)string { + return [MFStyler styleGetBoldMicroAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetBoldMicroAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontBoldMicro:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetRegularMicroAttributedString:(nullable NSString *)string { + return [MFStyler styleGetRegularBodySmallAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetRegularMicroAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontRegularMicro:genericScaling] color:[UIColor blackColor]]; +} + + +//2.0 font get attributedString + (nonnull NSAttributedString *)styleGetH1AttributedString:(nullable NSString *)string { return [MFStyler styleGetH1AttributedString:string genericScaling:YES]; } diff --git a/MVMCoreUI/Utility/MFFonts.h b/MVMCoreUI/Utility/MFFonts.h index 28e502c6..ba167df1 100644 --- a/MVMCoreUI/Utility/MFFonts.h +++ b/MVMCoreUI/Utility/MFFonts.h @@ -12,8 +12,17 @@ @interface MFFonts : NSObject +///return mfFontTXBold when size smaller than 15, otherwise, return mfFontDSBold + (nonnull UIFont *)mfFont75Bd:(CGFloat)size; +///return mfFontTXRegular when size smaller than 15, otherwise, return mfFontDSRegular + (nonnull UIFont *)mfFont55Rg:(CGFloat)size; + +//mva 3.0 font, should use mfFont75Bd/55Rg in most case. ++ (nonnull UIFont *)mfFontDSBold:(CGFloat)size; ++ (nonnull UIFont *)mfFontDSRegular:(CGFloat)size; ++ (nonnull UIFont *)mfFontTXBold:(CGFloat)size; ++ (nonnull UIFont *)mfFontTXRegular:(CGFloat)size; + + (nullable UIFont *)mfFontOcratxt:(CGFloat)size; + (nonnull UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size; diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 264dcf18..09956ae4 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -47,13 +47,30 @@ static NSString * const TXRegular = @"VerizonNHGeTX-Regular"; CFRelease(provider); } ++ (nonnull UIFont *)mfFontDSBold:(CGFloat)size { + return [UIFont fontWithName:DSBold size:size]; +} + ++ (nonnull UIFont *)mfFontDSRegular:(CGFloat)size { + return [UIFont fontWithName:DSRegular size:size]; +} + ++ (nonnull UIFont *)mfFontTXBold:(CGFloat)size { + return [UIFont fontWithName:TXBold size:size]; +} + ++ (nonnull UIFont *)mfFontTXRegular:(CGFloat)size { + return [UIFont fontWithName:TXRegular size:size]; +} + + + (UIFont *)mfFont75Bd:(CGFloat)size { [self loadMVMFonts]; UIFont *font; if (size >= 15) { - font = [UIFont fontWithName:DSBold size:size]; + font = [self mfFontDSBold:size]; } else { - font = [UIFont fontWithName:TXBold size:size]; + font = [self mfFontTXBold:size]; } return font ?: [UIFont boldSystemFontOfSize:size]; } @@ -62,9 +79,9 @@ static NSString * const TXRegular = @"VerizonNHGeTX-Regular"; [self loadMVMFonts]; UIFont *font; if (size >= 15) { - font = [UIFont fontWithName:DSRegular size:size]; + font = [self mfFontDSRegular:size]; } else { - font = [UIFont fontWithName:TXRegular size:size]; + font = [self mfFontTXRegular:size]; } return font ?: [UIFont systemFontOfSize:size]; } From 7be08fe9bea1fb2c5c450c296a2d546e79fe6495 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 25 Feb 2020 14:20:46 -0500 Subject: [PATCH 07/48] Stack fixes --- ...istOneColumnFullWidthTextAllTextAndLinks.swift | 15 ++++++++------- MVMCoreUI/Organisms/Stack.swift | 4 ++-- MVMCoreUI/Organisms/StackModel.swift | 5 ++++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index 9e930396..6f0ed557 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -36,22 +36,23 @@ import Foundation open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){ super.setWithModel(model, delegateObject, additionalData) - guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return} + guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return } eyebrow.setWithModel(model.eyebrow, delegateObject, additionalData) headline.setWithModel(model.headline, delegateObject, additionalData) subHeadline.setWithModel(model.subHeadline, delegateObject, additionalData) body.setWithModel(model.body, delegateObject, additionalData) link.setWithModel(model.link, delegateObject, additionalData) - let stackModel = StackModel(molecules: [StackItemModel(spacing: 2, gone: !eyebrow.hasText), - StackItemModel(spacing: 2, gone: !headline.hasText), - StackItemModel(spacing: 2, gone: !subHeadline.hasText), - StackItemModel(spacing: 2, gone: !body.hasText), - StackItemModel(spacing: 2, gone: (link.titleLabel?.text?.count ?? 0) == 0)]) + let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText), + StackItemModel(gone: !headline.hasText), + StackItemModel(gone: !subHeadline.hasText), + StackItemModel(gone: !body.hasText), + StackItemModel(spacing: 2, gone: (link.titleLabel?.text?.count ?? 0) == 0)], + spacing: 0) stack.model = stackModel stack.restack() } - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat?{ + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 90 } diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index 602ab0f1..0226412b 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -237,7 +237,7 @@ open class Stack: Container where T: StackModelProtocol { if first { pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: stackModel.useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0) } else if let previousView = stackItems.last(where: { item in - return !model.gone + return item.superview != nil }) { view.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: spacing).isActive = true } @@ -256,7 +256,7 @@ open class Stack: Container where T: StackModelProtocol { // First horizontal item has no spacing by default unless told otherwise. pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: stackModel.useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0) } else if let previousView = stackItems.last(where: { item in - return !model.gone + return item.superview != nil }) { view.leftAnchor.constraint(equalTo: previousView.rightAnchor, constant: spacing).isActive = true } diff --git a/MVMCoreUI/Organisms/StackModel.swift b/MVMCoreUI/Organisms/StackModel.swift index b762a03c..93712612 100644 --- a/MVMCoreUI/Organisms/StackModel.swift +++ b/MVMCoreUI/Organisms/StackModel.swift @@ -16,9 +16,12 @@ import Foundation public var spacing: CGFloat = 16.0 public var useStackSpacingBeforeFirstItem = false - public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis = .vertical) { + public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis = .vertical, spacing: CGFloat? = nil) { self.molecules = molecules self.axis = axis + if let spacing = spacing { + self.spacing = spacing + } } private enum CodingKeys: String, CodingKey { From 7891b7fdbd94cd08e0194d9bcce1c1b2df938116 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Wed, 26 Feb 2020 16:13:24 +0530 Subject: [PATCH 08/48] Added Folder --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 95bd45b6..152c1602 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -101,6 +101,7 @@ 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; }; 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; }; 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */; }; + 525019E0240680AC00EED91C /* FourColumn in Resources */ = {isa = PBXBuildFile; fileRef = 525019DF240680AC00EED91C /* FourColumn */; }; 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; }; 8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */; }; 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; }; @@ -435,6 +436,7 @@ 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = ""; }; 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = ""; }; 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDividerModel.swift; sourceTree = ""; }; + 525019DF240680AC00EED91C /* FourColumn */ = {isa = PBXFileReference; lastKnownFileType = folder; path = FourColumn; sourceTree = ""; }; 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = ""; }; 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaretModel.swift; sourceTree = ""; }; 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = ""; }; @@ -1024,6 +1026,7 @@ D22B38EC23F4E10700490EF6 /* SectionDividers */ = { isa = PBXGroup; children = ( + 525019DF240680AC00EED91C /* FourColumn */, 52267A0523FFE0A900906CBA /* OneColumn */, D22B38ED23F4E11100490EF6 /* ThreeColumn */, ); @@ -1629,6 +1632,7 @@ files = ( D29DF2AF21E7B3A4003B2FB9 /* MFTextView.xib in Resources */, D29DF31C21ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf in Resources */, + 525019E0240680AC00EED91C /* FourColumn in Resources */, D29DF31D21ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf in Resources */, 0A21DB8E235E06EF00C160A2 /* MFDigitTextField.xib in Resources */, D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */, From e31918c0519c0aa34e43a8506cfcaa3849eb59a6 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Wed, 26 Feb 2020 16:19:51 +0530 Subject: [PATCH 09/48] Error in referencing. --- MVMCoreUI.xcodeproj/project.pbxproj | 4 -- .../ListFourColumnDataUsageDivider.swift | 72 ------------------- .../ListFourColumnDataUsageDividerModel.swift | 59 --------------- 3 files changed, 135 deletions(-) delete mode 100644 MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift delete mode 100644 MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 152c1602..95bd45b6 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -101,7 +101,6 @@ 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; }; 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; }; 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */; }; - 525019E0240680AC00EED91C /* FourColumn in Resources */ = {isa = PBXBuildFile; fileRef = 525019DF240680AC00EED91C /* FourColumn */; }; 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; }; 8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */; }; 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; }; @@ -436,7 +435,6 @@ 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = ""; }; 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = ""; }; 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDividerModel.swift; sourceTree = ""; }; - 525019DF240680AC00EED91C /* FourColumn */ = {isa = PBXFileReference; lastKnownFileType = folder; path = FourColumn; sourceTree = ""; }; 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = ""; }; 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaretModel.swift; sourceTree = ""; }; 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = ""; }; @@ -1026,7 +1024,6 @@ D22B38EC23F4E10700490EF6 /* SectionDividers */ = { isa = PBXGroup; children = ( - 525019DF240680AC00EED91C /* FourColumn */, 52267A0523FFE0A900906CBA /* OneColumn */, D22B38ED23F4E11100490EF6 /* ThreeColumn */, ); @@ -1632,7 +1629,6 @@ files = ( D29DF2AF21E7B3A4003B2FB9 /* MFTextView.xib in Resources */, D29DF31C21ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf in Resources */, - 525019E0240680AC00EED91C /* FourColumn in Resources */, D29DF31D21ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf in Resources */, 0A21DB8E235E06EF00C160A2 /* MFDigitTextField.xib in Resources */, D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */, diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift deleted file mode 100644 index 6fc99c94..00000000 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift +++ /dev/null @@ -1,72 +0,0 @@ -// -// ListFourColumnDataUsageDivider.swift -// MVMCoreUI -// -// Created by Lekshmi S on 18/02/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -@objcMembers open class ListFourColumnDataUsageDivider: TableViewCell { - - //------------------------------------------------------- - // MARK: - Outlets - //------------------------------------------------------- - let label1 = Label.commonLabelB1(true) - let label2 = Label.commonLabelB1(true) - let label3 = Label.commonLabelB1(true) - let label4 = Label.commonLabelB1(true) - let stack = Stack(frame: .zero) - - //------------------------------------------------------- - // MARK: - View Lifecycle - //------------------------------------------------------- - open override func updateView(_ size: CGFloat) { - super.updateView(size) - stack.updateView(size) - } - - open override func setupView() { - super.setupView() - stack.translatesAutoresizingMaskIntoConstraints = false - stack.stackItems = [StackItem(andContain: label1), StackItem(andContain: label2), StackItem(andContain: label3), StackItem(andContain: label4)] - contentView.addSubview(stack) - containerHelper.constrainView(stack) - } - - //------------------------------------------------------ - // MARK: - Molecule - //------------------------------------------------------ - open override func reset() { - super.reset() - stack.reset() - } - - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) - guard let model = model as? ListFourColumnDataUsageDividerModel else { return } - label1.setWithModel(model.label1, delegateObject, additionalData) - label2.setWithModel(model.label2, delegateObject, additionalData) - label3.setWithModel(model.label3, delegateObject, additionalData) - label4.setWithModel(model.label4, delegateObject, additionalData) - - //Create a stack model to use for the internal stack and set the alignment of labels - let label1 = StackItemModel(percent: 20) - label1.horizontalAlignment = .leading - let label2 = StackItemModel(percent: 40) - label2.horizontalAlignment = .leading - let label3 = StackItemModel(percent: 20) - label3.horizontalAlignment = .leading - let label4 = StackItemModel(percent: 20) - label4.horizontalAlignment = .leading - let stackModel = StackModel(molecules: [label1, label2, label3, label4]) - stackModel.axis = .horizontal - stack.model = stackModel - stack.restack() - } - - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - return 90 - } -} diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift deleted file mode 100644 index e07ca87f..00000000 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// ListFourColumnDataUsageDividerModel.swift -// MVMCoreUI -// -// Created by Lekshmi S on 18/02/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -public class ListFourColumnDataUsageDividerModel: ListItemModel, MoleculeModelProtocol { - public static var identifier: String = "list4CDiv" - public var label1: LabelModel? - public var label2: LabelModel? - public var label3: LabelModel? - public var label4: LabelModel? - - public init(label1: LabelModel, label2: LabelModel, label3: LabelModel, label4: LabelModel) { - self.label1 = label1 - self.label2 = label2 - self.label3 = label3 - self.label4 = label4 - super.init() - setDefaults() - } - - // Defaults to set - override public func setDefaults() { - super.setDefaults() - style = "tallDivider" - } - - private enum CodingKeys: String, CodingKey { - case moleculeName - case label1 - case label2 - case label3 - case label4 - } - - required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - label1 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .label1) - label2 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .label2) - label3 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .label3) - label4 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .label4) - try super.init(from: decoder) - } - - public override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(label1, forKey: .label1) - try container.encodeIfPresent(label2, forKey: .label2) - try container.encodeIfPresent(label3, forKey: .label3) - try container.encodeIfPresent(label4, forKey: .label4) - } -} From 224148d36ffd6e3f11375cf2d9abd962d7b01c46 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Wed, 26 Feb 2020 19:03:42 +0530 Subject: [PATCH 10/48] Code improvement. --- MVMCoreUI.xcodeproj/project.pbxproj | 16 +++++ .../ListFourColumnDataUsageDivider.swift | 60 +++++++++++++++++++ .../ListFourColumnDataUsageDividerModel.swift | 59 ++++++++++++++++++ .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 4 files changed, 136 insertions(+) create mode 100644 MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift create mode 100644 MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 95bd45b6..4989a5c6 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -101,6 +101,8 @@ 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; }; 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; }; 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */; }; + 525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525019E42406852100EED91C /* ListFourColumnDataUsageDividerModel.swift */; }; + 525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525019E62406853600EED91C /* ListFourColumnDataUsageDivider.swift */; }; 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; }; 8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */; }; 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; }; @@ -435,6 +437,8 @@ 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = ""; }; 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = ""; }; 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDividerModel.swift; sourceTree = ""; }; + 525019E42406852100EED91C /* ListFourColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageDividerModel.swift; sourceTree = ""; }; + 525019E62406853600EED91C /* ListFourColumnDataUsageDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageDivider.swift; sourceTree = ""; }; 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = ""; }; 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaretModel.swift; sourceTree = ""; }; 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = ""; }; @@ -781,6 +785,15 @@ path = OneColumn; sourceTree = ""; }; + 525019E3240684E500EED91C /* FourColumn */ = { + isa = PBXGroup; + children = ( + 525019E42406852100EED91C /* ListFourColumnDataUsageDividerModel.swift */, + 525019E62406853600EED91C /* ListFourColumnDataUsageDivider.swift */, + ); + path = FourColumn; + sourceTree = ""; + }; 946EE1B5237B663A0036751F /* Extensions */ = { isa = PBXGroup; children = ( @@ -1024,6 +1037,7 @@ D22B38EC23F4E10700490EF6 /* SectionDividers */ = { isa = PBXGroup; children = ( + 525019E3240684E500EED91C /* FourColumn */, 52267A0523FFE0A900906CBA /* OneColumn */, D22B38ED23F4E11100490EF6 /* ThreeColumn */, ); @@ -1758,6 +1772,7 @@ D2B18B812360945C00A9AEDC /* View.swift in Sources */, C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */, D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, + 525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */, 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */, 94FB966323D797DA003D482B /* MFTextButton.m in Sources */, D260105323CEA61600764D80 /* ToggleModel.swift in Sources */, @@ -1818,6 +1833,7 @@ 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */, D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, + 525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, 0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */, D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */, diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift new file mode 100644 index 00000000..cd103787 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift @@ -0,0 +1,60 @@ +// +// ListFourColumnDataUsageDivider.swift +// MVMCoreUI +// +// Created by Lekshmi S on 18/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class ListFourColumnDataUsageDivider: TableViewCell { + + // MARK: - MFViewProtocol + let label1 = Label.commonLabelB1(true) + let label2 = Label.commonLabelB1(true) + let label3 = Label.commonLabelB1(true) + let label4 = Label.commonLabelB1(true) + let stack = Stack(frame: .zero) + + // MARK: - MFViewProtocol + open override func setupView() { + super.setupView() + stack.stackItems = [StackItem(andContain: label1), + StackItem(andContain: label2), + StackItem(andContain: label3), + StackItem(andContain: label4)] + addMolecule(stack) + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? ListFourColumnDataUsageDividerModel else { return } + label1.setWithModel(model.label1, delegateObject, additionalData) + label2.setWithModel(model.label2, delegateObject, additionalData) + label3.setWithModel(model.label3, delegateObject, additionalData) + label4.setWithModel(model.label4, delegateObject, additionalData) + //Create a stack model to use for the internal stack and set the alignment of labels + let stackModel = StackModel(molecules: [StackItemModel(percent: 15, horizontalAlignment: .leading), + StackItemModel(percent: 35, horizontalAlignment: .leading), + StackItemModel(percent: 30, horizontalAlignment: .trailing), + StackItemModel(percent: 20, horizontalAlignment: .trailing)], + axis: .horizontal) + stack.model = stackModel + stack.restack() + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + open override func reset() { + super.reset() + label1.styleB1(true) + label2.styleB1(true) + label3.styleB1(true) + label4.styleB1(true) + } + + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 121 + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift new file mode 100644 index 00000000..1277f4bb --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift @@ -0,0 +1,59 @@ +// +// ListFourColumnDataUsageDividerModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 18/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListFourColumnDataUsageDividerModel: ListItemModel, MoleculeModelProtocol { + public static var identifier: String = "list4CDiv" + public var label1: LabelModel + public var label2: LabelModel + public var label3: LabelModel + public var label4: LabelModel + + public init(label1: LabelModel, label2: LabelModel, label3: LabelModel, label4: LabelModel) { + self.label1 = label1 + self.label2 = label2 + self.label3 = label3 + self.label4 = label4 + super.init() + setDefaults() + } + + // Defaults to set + override public func setDefaults() { + super.setDefaults() + style = "tallDivider" + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case label1 + case label2 + case label3 + case label4 + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + label1 = try typeContainer.decode(LabelModel.self, forKey: .label1) + label2 = try typeContainer.decode(LabelModel.self, forKey: .label2) + label3 = try typeContainer.decode(LabelModel.self, forKey: .label3) + label4 = try typeContainer.decode(LabelModel.self, forKey: .label4) + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(label1, forKey: .label1) + try container.encode(label2, forKey: .label2) + try container.encode(label3, forKey: .label3) + try container.encode(label4, forKey: .label4) + } +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 30efb2f7..92169d58 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -56,6 +56,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) From e54c87becf9f597cdfc7724a97af83576048db13 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 11:06:34 -0500 Subject: [PATCH 11/48] update font --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++++ MVMCoreUI/Atoms/Views/Label/Label.swift | 16 +++++----- MVMCoreUI/MVMCoreUI.h | 1 + MVMCoreUI/Styles/MFStyler.h | 2 ++ MVMCoreUI/Styles/MFStyler.m | 40 +++++++++++++++++-------- MVMCoreUI/Utility/MFFonts.h | 5 ++++ MVMCoreUI/Utility/MFFonts.m | 8 ++--- MVMCoreUI/Utility/UIFont+FontWrapping.h | 19 ++++++++++++ MVMCoreUI/Utility/UIFont+FontWrapping.m | 25 ++++++++++++++++ 9 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 MVMCoreUI/Utility/UIFont+FontWrapping.h create mode 100644 MVMCoreUI/Utility/UIFont+FontWrapping.m diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index cb821240..a28f633b 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -111,6 +111,8 @@ 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944589202385D6E900DE9FD4 /* DashLineModel.swift */; }; 944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944589222385DA9500DE9FD4 /* ImageViewModel.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; + 9458C3172406C8FD00930963 /* UIFont+FontWrapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9458C3182406C8FD00930963 /* UIFont+FontWrapping.m in Sources */ = {isa = PBXBuildFile; fileRef = 9458C3162406C8FD00930963 /* UIFont+FontWrapping.m */; }; 946EE1BA237B66D80036751F /* MoleculeModelHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946EE1B9237B66D80036751F /* MoleculeModelHelper.swift */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; 94AF4A3E23E9D13900676048 /* MFCaretButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AF4A3C23E9D13900676048 /* MFCaretButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -445,6 +447,8 @@ 944589202385D6E900DE9FD4 /* DashLineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashLineModel.swift; sourceTree = ""; }; 944589222385DA9500DE9FD4 /* ImageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewModel.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; + 9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIFont+FontWrapping.h"; sourceTree = ""; }; + 9458C3162406C8FD00930963 /* UIFont+FontWrapping.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+FontWrapping.m"; sourceTree = ""; }; 946EE1B9237B66D80036751F /* MoleculeModelHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeModelHelper.swift; sourceTree = ""; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; 94AF4A3C23E9D13900676048 /* MFCaretButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFCaretButton.h; sourceTree = ""; }; @@ -1234,6 +1238,8 @@ D29DF28121E7AB23003B2FB9 /* MVMCoreUICommonViewsUtility.m */, D29DF14D21E693AD003B2FB9 /* MFFonts.h */, D29DF14C21E693AD003B2FB9 /* MFFonts.m */, + 9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */, + 9458C3162406C8FD00930963 /* UIFont+FontWrapping.m */, D29DF29F21E7AF4E003B2FB9 /* MVMCoreUIUtility.h */, D29DF2A021E7AF4E003B2FB9 /* MVMCoreUIUtility.m */, D29DF2A721E7B2F9003B2FB9 /* MVMCoreUIConstants.h */, @@ -1497,6 +1503,7 @@ D29770F421F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h in Headers */, D29DF15421E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h in Headers */, D2A514582211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h in Headers */, + 9458C3172406C8FD00930963 /* UIFont+FontWrapping.h in Headers */, D29DF0D121E404D4003B2FB9 /* MVMCoreUI.h in Headers */, D29DF29A21E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h in Headers */, D29DF11521E6805F003B2FB9 /* UIColor+MFConvenience.h in Headers */, @@ -1674,6 +1681,7 @@ DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */, D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */, 017BEB442362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift in Sources */, + 9458C3182406C8FD00930963 /* UIFont+FontWrapping.m in Sources */, 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */, 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */, 9445891F2385D2E900DE9FD4 /* CaretViewModel.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index 5e11e116..70e54e45 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -350,7 +350,7 @@ public typealias ActionBlock = () -> () if let fontName = labelModel.fontName { font = MFFonts.mfFont(withName: fontName, size: fontSize ?? standardFontSize) } else if let fontSize = fontSize { - font = font.withSize(fontSize) + font = font.updateSize(fontSize) } } @@ -359,7 +359,7 @@ public typealias ActionBlock = () -> () } if let attributes = labelModel.attributes, let labelText = text { - let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font.withSize(standardFontSize), NSAttributedString.Key.foregroundColor: textColor as UIColor]) + let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font.updateSize(standardFontSize), NSAttributedString.Key.foregroundColor: textColor as UIColor]) for attribute in attributes { let range = NSRange(location: attribute.location, length: attribute.length) @@ -407,7 +407,7 @@ public typealias ActionBlock = () -> () if let fontName = fontAtt.name { font = MFFonts.mfFont(withName: fontName, size: fontSize ?? self.font.pointSize) } else if let fontSize = fontSize { - font = self.font.withSize(fontSize) + font = self.font.updateSize(fontSize) } if let font = font { attributedString.removeAttribute(.font, range: range) @@ -473,7 +473,7 @@ public typealias ActionBlock = () -> () if let fontName = json?.optionalStringForKey("fontName") { label.font = MFFonts.mfFont(withName: fontName, size: fontSize ?? mvmLabel?.standardFontSize ?? label.font.pointSize) } else if let fontSize = fontSize { - label.font = label.font.withSize(fontSize) + label.font = label.font.updateSize(fontSize) } } @@ -483,7 +483,7 @@ public typealias ActionBlock = () -> () if let attributes = json?.optionalArrayForKey("attributes"), let labelText = label.text { let attributedString = NSMutableAttributedString(string: labelText, - attributes: [NSAttributedString.Key.font: mvmLabel?.font.withSize(mvmLabel!.standardFontSize) ?? label.font as UIFont, + attributes: [NSAttributedString.Key.font: mvmLabel?.font.updateSize(mvmLabel!.standardFontSize) ?? label.font as UIFont, NSAttributedString.Key.foregroundColor: label.textColor as UIColor]) for case let attribute as [String: Any] in attributes { guard let attributeType = attribute.optionalStringForKey(KeyType), @@ -535,7 +535,7 @@ public typealias ActionBlock = () -> () if let fontName = attribute.optionalStringForKey("name") { font = MFFonts.mfFont(withName: fontName, size: fontSize ?? mvmLabel?.standardFontSize ?? label.font.pointSize) } else if let fontSize = fontSize { - font = label.font.withSize(fontSize) + font = label.font.updateSize(fontSize) } if let font = font { @@ -677,7 +677,7 @@ public typealias ActionBlock = () -> () originalAttributedString.enumerateAttribute(.font, in: NSRange(location: 0, length: originalAttributedString.length), options: []) { value, range, stop in if let fontObj = value as? UIFont, let stylerSize = MFStyler.sizeObjectGeneric(forCurrentDevice: fontObj.pointSize)?.getValueBased(onSize: size) { - attributedString.addAttribute(.font, value: fontObj.withSize(stylerSize) as Any, range: range) + attributedString.addAttribute(.font, value: fontObj.updateSize(stylerSize) as Any, range: range) } } @@ -693,7 +693,7 @@ public typealias ActionBlock = () -> () attributedText = attributedString } else if !MVMCoreGetterUtility.fequal(a: Float(standardFontSize), b: 0.0), let sizeObject = sizeObject ?? MFStyler.sizeObjectGeneric(forCurrentDevice: standardFontSize) { - font = font.withSize(sizeObject.getValueBased(onSize: size)) + font = font.updateSize(sizeObject.getValueBased(onSize: size)) } } diff --git a/MVMCoreUI/MVMCoreUI.h b/MVMCoreUI/MVMCoreUI.h index 1b2183aa..5e8c92cc 100644 --- a/MVMCoreUI/MVMCoreUI.h +++ b/MVMCoreUI/MVMCoreUI.h @@ -32,6 +32,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; #pragma mark - Categories #import #import +#import #pragma mark - Styles #import diff --git a/MVMCoreUI/Styles/MFStyler.h b/MVMCoreUI/Styles/MFStyler.h index eb89312c..6accea28 100644 --- a/MVMCoreUI/Styles/MFStyler.h +++ b/MVMCoreUI/Styles/MFStyler.h @@ -100,6 +100,8 @@ B3 -> Legal // Returns the fonts for these styles. Scales them as needed by default #pragma mark - 3.0 fonts +///auto select corresponding font based on font size, DS for font bigger than 15 pt, TX for font smaller than 15 pt ++ (nonnull UIFont *)getMVA3FontSize:(CGFloat)size bold:(BOOL)isBold; ///Bold 36pt + (nonnull UIFont *)fontTitle2XLarge:(BOOL)genericScaling; + (nonnull UIFont *)fontTitle2XLarge; diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index 69a04b3e..55978976 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -113,12 +113,28 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; #pragma mark - 3.0 fonts ++ (nonnull UIFont *)getMVA3FontSize:(CGFloat)size bold:(BOOL)isBold { + if (isBold) { + if (size >= 15) { + return [MFFonts mfFontDSBold:size]; + } else { + return [MFFonts mfFontTXBold:size]; + } + } else { + if (size >= 15) { + return [MFFonts mfFontDSRegular:size]; + } else { + return [MFFonts mfFontTXRegular:size]; + } + } +} + + (nonnull UIFont *)fontTitle2XLarge:(BOOL)genericScaling { CGFloat size = 36; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontTitle2XLarge { @@ -130,7 +146,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontTitleXLarge{ return [self fontTitleXLarge:YES]; @@ -141,7 +157,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontBoldTitleLarge { @@ -153,7 +169,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont55Rg:size]; + return [self getMVA3FontSize:size bold:NO]; } + (nonnull UIFont *)fontRegularTitleLarge { @@ -165,7 +181,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontBoldTitleMedium { @@ -177,7 +193,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont55Rg:size]; + return [self getMVA3FontSize:size bold:NO]; } + (nonnull UIFont *)fontRegularTitleMedium { @@ -189,7 +205,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontBoldBodyLarge { @@ -201,7 +217,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont55Rg:size]; + return [self getMVA3FontSize:size bold:NO]; } + (nonnull UIFont *)fontRegularBodyLarge { @@ -213,7 +229,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontBoldBodySmall { @@ -225,7 +241,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont55Rg:size]; + return [self getMVA3FontSize:size bold:NO]; } + (nonnull UIFont *)fontRegularBodySmall { @@ -237,7 +253,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontBoldMicro { @@ -249,7 +265,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont55Rg:size]; + return [self getMVA3FontSize:size bold:NO]; } + (nonnull UIFont *)fontRegularMicro { diff --git a/MVMCoreUI/Utility/MFFonts.h b/MVMCoreUI/Utility/MFFonts.h index ba167df1..4bd1f532 100644 --- a/MVMCoreUI/Utility/MFFonts.h +++ b/MVMCoreUI/Utility/MFFonts.h @@ -10,6 +10,11 @@ #import #import +extern NSString * _Nonnull const DSBold; +extern NSString * _Nonnull const DSRegular; +extern NSString * _Nonnull const TXBold; +extern NSString * _Nonnull const TXRegular; + @interface MFFonts : NSObject ///return mfFontTXBold when size smaller than 15, otherwise, return mfFontDSBold diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 09956ae4..964707a0 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -11,10 +11,10 @@ #import "MVMCoreUIUtility.h" @import MVMCore.MVMCoreLoggingHandler; -static NSString * const DSBold = @"VerizonNHGeDS-Bold"; -static NSString * const DSRegular = @"VerizonNHGeDS-Regular"; -static NSString * const TXBold = @"VerizonNHGeTX-Bold"; -static NSString * const TXRegular = @"VerizonNHGeTX-Regular"; +NSString * const DSBold = @"VerizonNHGeDS-Bold"; +NSString * const DSRegular = @"VerizonNHGeDS-Regular"; +NSString * const TXBold = @"VerizonNHGeTX-Bold"; +NSString * const TXRegular = @"VerizonNHGeTX-Regular"; @implementation MFFonts diff --git a/MVMCoreUI/Utility/UIFont+FontWrapping.h b/MVMCoreUI/Utility/UIFont+FontWrapping.h new file mode 100644 index 00000000..1fd3360d --- /dev/null +++ b/MVMCoreUI/Utility/UIFont+FontWrapping.h @@ -0,0 +1,19 @@ +// +// UIFont+FontWrapping.h +// MVMCoreUI +// +// Created by Ryan on 2/26/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIFont (FontWrapping) + +- (UIFont *)updateFontSize:(CGFloat)size; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MVMCoreUI/Utility/UIFont+FontWrapping.m b/MVMCoreUI/Utility/UIFont+FontWrapping.m new file mode 100644 index 00000000..8af7783d --- /dev/null +++ b/MVMCoreUI/Utility/UIFont+FontWrapping.m @@ -0,0 +1,25 @@ +// +// UIFont+FontWrapping.m +// MVMCoreUI +// +// Created by Ryan on 2/26/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +#import "UIFont+FontWrapping.h" +#import "MFFonts.h" +#import "MFStyler.h" +#import + +@implementation UIFont (FontWrapping) + +- (UIFont *)updateFontSize:(CGFloat)size { + if ([self.familyName isEqualToString:@"Verizon NHG eDS"] || [self.familyName isEqualToString:@"Verizon NHG eTX"]) { + return [MFStyler getMVA3FontSize:size bold:[self.fontName isEqualToString:DSBold]]; + } else { + return [self fontWithSize:size]; + } + +} + +@end From 16f49329f7fae62cda52b607f7c9a18b6ae86f89 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 12:35:44 -0500 Subject: [PATCH 12/48] update create label method name --- MVMCoreUI/Atoms/Views/Label/Label.swift | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index 70e54e45..6550d307 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -133,82 +133,82 @@ public typealias ActionBlock = () -> () //------------------------------------------------------ /// Title 2XLarge - @objc public static func commonLabelTitle2XLarge(_ scale: Bool) -> Label { + @objc public static func createLabelTitle2XLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleTitle2XLarge(scale) return label } /// TitleXLarge - @objc public static func commonLabelTitleXLarge(_ scale: Bool) -> Label { + @objc public static func createLabelTitleXLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleTitleXLarge(scale) return label } /// BoldTitleLarge - @objc public static func commonLabelBoldTitleLarge(_ scale: Bool) -> Label { + @objc public static func createLabelBoldTitleLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleBoldTitleLarge(scale) return label } /// RegularTitleLarge - @objc public static func commonLabelRegularTitleLarge(_ scale: Bool) -> Label { + @objc public static func createLabelRegularTitleLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleRegularTitleLarge(scale) return label } /// BoldTitleMedium - @objc public static func commonLabelBoldTitleMedium(_ scale: Bool) -> Label { + @objc public static func createLabelBoldTitleMedium(_ scale: Bool) -> Label { let label = Label.label() label.styleBoldTitleMedium(scale) return label } /// RegularTitleMedium - @objc public static func commonLabelRegularTitleMedium(_ scale: Bool) -> Label { + @objc public static func createLabelRegularTitleMedium(_ scale: Bool) -> Label { let label = Label.label() label.styleRegularTitleMedium(scale) return label } /// BoldBodyLarge - @objc public static func commonLabelBoldBodyLarge(_ scale: Bool) -> Label { + @objc public static func createLabelBoldBodyLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleBoldBodyLarge(scale) return label } /// RegularBodyLarge - @objc public static func commonLabelRegularBodyLarge(_ scale: Bool) -> Label { + @objc public static func createLabelRegularBodyLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleRegularBodyLarge(scale) return label } /// BoldBodySmall - @objc public static func commonLabelBoldBodySmall(_ scale: Bool) -> Label { + @objc public static func createLabelBoldBodySmall(_ scale: Bool) -> Label { let label = Label.label() label.styleBoldBodySmall(scale) return label } /// RegularBodySmall - @objc public static func commonLabelRegularBodySmall(_ scale: Bool) -> Label { + @objc public static func createLabelRegularBodySmall(_ scale: Bool) -> Label { let label = Label.label() label.styleRegularBodySmall(scale) return label } /// BoldMicro - @objc public static func commonLabelBoldMicro(_ scale: Bool) -> Label { + @objc public static func createLabelBoldMicro(_ scale: Bool) -> Label { let label = Label.label() label.styleBoldMicro(scale) return label } /// RegularMicro - @objc public static func commonLabelRegularMicro(_ scale: Bool) -> Label { + @objc public static func createLabelRegularMicro(_ scale: Bool) -> Label { let label = Label.label() label.styleRegularMicro(scale) return label From 1d7fb0d219046e68a3b2b1af8b29d1719097445d Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 12:45:06 -0500 Subject: [PATCH 13/48] change font of top navigation from 14 to 13 for new design --- MVMCoreUI/Containers/NavigationController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index e10f09c5..524ec68c 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -20,7 +20,7 @@ import UIKit navigationBar.shadowImage = UIImage() navigationBar.isOpaque = true navigationBar.tintColor = .black - let font = MFFonts.mfFont75Bd(MFSizeObject(standardSize: 14, standardiPadPortraitSize: 16, iPadProLandscapeSize: 18)?.getValueBasedOnScreenSize() ?? 14) + let font = MFFonts.mfFont75Bd(MFSizeObject(standardSize: 13, standardiPadPortraitSize: 16, iPadProLandscapeSize: 18)?.getValueBasedOnScreenSize() ?? 13) navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font]; } From 4b31b191743bfe0623e7c69ed50186969e27e823 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 13:00:40 -0500 Subject: [PATCH 14/48] update font --- MVMCoreUI/Containers/NavigationController.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 524ec68c..6e18e427 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -20,9 +20,7 @@ import UIKit navigationBar.shadowImage = UIImage() navigationBar.isOpaque = true navigationBar.tintColor = .black - let font = MFFonts.mfFont75Bd(MFSizeObject(standardSize: 13, standardiPadPortraitSize: 16, iPadProLandscapeSize: 18)?.getValueBasedOnScreenSize() ?? 13) - - navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font]; + navigationBar.titleTextAttributes = [NSAttributedString.Key.font: MFStyler.fontBoldBodySmall(false)]; } public static func setupNavigationController() -> Self? { From 8ff8f9aa3ad0e8aa493784636174db0435a664d7 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 26 Feb 2020 13:21:43 -0500 Subject: [PATCH 15/48] external icon convenience --- .../Atoms/Buttons/Link/ExternalLink.swift | 68 +++++++------------ .../Buttons/Link/ExternalLinkModel.swift | 2 +- 2 files changed, 27 insertions(+), 43 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift index 3f0aa5d6..b8026f99 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift @@ -10,6 +10,12 @@ import UIKit open class ExternalLink: Link { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + private var exportImageView: UIImageView? + //-------------------------------------------------- // MARK: - ModelMoleculeViewProtocol //-------------------------------------------------- @@ -19,55 +25,33 @@ open class ExternalLink: Link { guard let model = model as? ExternalLinkModel else { return } + exportImageView?.tintColor = model.textColor.uiColor } -} - -// MARK: - MVMCoreViewProtocol -extension ExternalLink { - public override func updateView(_ size: CGFloat) { - super.updateView(size) - } + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- public override func setupView() { super.setupView() - - let imageView = UIImageView(image: MVMCoreUIUtility.imageNamed("externalLink")) - imageView.contentMode = .scaleAspectFit - imageView.translatesAutoresizingMaskIntoConstraints = false - - addSubview(imageView) - imageView.heightAnchor.constraint(equalToConstant: round(0.8 * titleLabel!.font.pointSize)).isActive = true - imageView.widthAnchor.constraint(equalToConstant: round(0.8 * titleLabel!.font.pointSize)).isActive = true + let image = MVMCoreUIUtility.imageNamed("externalLink") + exportImageView = UIImageView(image: image?.withRenderingMode(.alwaysTemplate)) - imageView.leadingAnchor.constraint(equalTo: titleLabel!.trailingAnchor, constant: PaddingOne).isActive = true - trailingAnchor.constraint(greaterThanOrEqualTo: imageView.trailingAnchor).isActive = true + guard let exportIcon = exportImageView else { return } - imageView.bottomAnchor.constraint(equalTo: titleLabel!.lastBaselineAnchor).isActive = true + exportIcon.contentMode = .scaleAspectFit + exportIcon.translatesAutoresizingMaskIntoConstraints = false + + addSubview(exportIcon) + trailingAnchor.constraint(greaterThanOrEqualTo: exportIcon.trailingAnchor).isActive = true + + if let titleLabel = titleLabel { + let dimension = round(0.6 * titleLabel.font.pointSize) + exportIcon.heightAnchor.constraint(equalToConstant: dimension).isActive = true + exportIcon.widthAnchor.constraint(equalToConstant: dimension).isActive = true + exportIcon.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: PaddingOne).isActive = true + exportIcon.bottomAnchor.constraint(equalTo: titleLabel.lastBaselineAnchor).isActive = true + } } } - -/* - static func getTextAttachmentFrom(url: String, dimension: CGFloat, label: Label) -> NSTextAttachment { - - let dimension = round(dimension * 0.8) - - let imageAttachment = NSTextAttachment() - imageAttachment.bounds = CGRect(x: 0, y: 0, width: dimension, height: dimension) - - DispatchQueue.global(qos: .default).async { - - guard let url = URL(string: url), - let data = try? Data(contentsOf: url) - else { return } - - DispatchQueue.main.sync { - imageAttachment.image = UIImage(data: data) - label.setNeedsDisplay() - } - } - - return imageAttachment - } - */ diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift index a7fc5211..070e501e 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift @@ -8,7 +8,7 @@ import UIKit -class ExternalLinkModel: LinkModel { +public class ExternalLinkModel: LinkModel { override public class var identifier: String { return "externalLink" From 80b2513feb58e9d674c533820d6fcdd588d7b52a Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 13:28:23 -0500 Subject: [PATCH 16/48] fix semi colon paste in m file --- MVMCoreUI/Containers/TabBarController/TopTabbar.m | 2 +- MVMCoreUI/Styles/MFStyler.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Containers/TabBarController/TopTabbar.m b/MVMCoreUI/Containers/TabBarController/TopTabbar.m index e9d77c77..4b89903f 100644 --- a/MVMCoreUI/Containers/TabBarController/TopTabbar.m +++ b/MVMCoreUI/Containers/TabBarController/TopTabbar.m @@ -338,7 +338,7 @@ static NSString * const COLLECTION_CELL_ID = @"cell"; #pragma mark - helper -- (void)pinHeight:(CGFloat)height; { +- (void)pinHeight:(CGFloat)height { self.heightConstraint.constant = height; [self setNeedsLayout]; [self layoutIfNeeded]; diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index 55978976..213c205e 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -1019,7 +1019,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; return [MFStyler styleGetTitle2XLargeAttributedString:string genericScaling:YES]; } -+ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; { ++ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { return [MFStyler styleGetAttributedString:string font:[MFStyler fontTitle2XLarge:genericScaling] color:[UIColor blackColor]]; } From fcc21ebf283657f0105fd544edfe32e082bdb700 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 13:34:01 -0500 Subject: [PATCH 17/48] fix typo --- MVMCoreUI/Utility/MFFonts.h | 11 +++++------ MVMCoreUI/Utility/UIFont+FontWrapping.m | 4 +++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Utility/MFFonts.h b/MVMCoreUI/Utility/MFFonts.h index 4bd1f532..46947581 100644 --- a/MVMCoreUI/Utility/MFFonts.h +++ b/MVMCoreUI/Utility/MFFonts.h @@ -17,17 +17,16 @@ extern NSString * _Nonnull const TXRegular; @interface MFFonts : NSObject -///return mfFontTXBold when size smaller than 15, otherwise, return mfFontDSBold -+ (nonnull UIFont *)mfFont75Bd:(CGFloat)size; -///return mfFontTXRegular when size smaller than 15, otherwise, return mfFontDSRegular -+ (nonnull UIFont *)mfFont55Rg:(CGFloat)size; - -//mva 3.0 font, should use mfFont75Bd/55Rg in most case. +//mva 3.0 font, should use MFStyler.getMVA3FontSize:bold: instead, in most case. + (nonnull UIFont *)mfFontDSBold:(CGFloat)size; + (nonnull UIFont *)mfFontDSRegular:(CGFloat)size; + (nonnull UIFont *)mfFontTXBold:(CGFloat)size; + (nonnull UIFont *)mfFontTXRegular:(CGFloat)size; +///return mfFontTXBold when size smaller than 15, otherwise, return mfFontDSBold ++ (nonnull UIFont *)mfFont75Bd:(CGFloat)size; +///return mfFontTXRegular when size smaller than 15, otherwise, return mfFontDSRegular ++ (nonnull UIFont *)mfFont55Rg:(CGFloat)size; + (nullable UIFont *)mfFontOcratxt:(CGFloat)size; + (nonnull UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size; diff --git a/MVMCoreUI/Utility/UIFont+FontWrapping.m b/MVMCoreUI/Utility/UIFont+FontWrapping.m index 8af7783d..a3fa2429 100644 --- a/MVMCoreUI/Utility/UIFont+FontWrapping.m +++ b/MVMCoreUI/Utility/UIFont+FontWrapping.m @@ -14,8 +14,10 @@ @implementation UIFont (FontWrapping) - (UIFont *)updateFontSize:(CGFloat)size { - if ([self.familyName isEqualToString:@"Verizon NHG eDS"] || [self.familyName isEqualToString:@"Verizon NHG eTX"]) { + if ([self.familyName isEqualToString:@"Verizon NHG eDS"]) { return [MFStyler getMVA3FontSize:size bold:[self.fontName isEqualToString:DSBold]]; + } else if ([self.familyName isEqualToString:@"Verizon NHG eTX"]) { + return [MFStyler getMVA3FontSize:size bold:[self.fontName isEqualToString:TXBold]]; } else { return [self fontWithSize:size]; } From 73bd5ebafc5596c18cf9fd48ac766209c6c7b103 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 26 Feb 2020 13:36:02 -0500 Subject: [PATCH 18/48] wipppp --- MVMCoreUI/Atoms/Views/Arrow.swift | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Arrow.swift b/MVMCoreUI/Atoms/Views/Arrow.swift index f2e98abb..2103d73f 100644 --- a/MVMCoreUI/Atoms/Views/Arrow.swift +++ b/MVMCoreUI/Atoms/Views/Arrow.swift @@ -8,14 +8,16 @@ import UIKit -class Arrow: View { +open class Arrow: View { - /* - // Only override draw() if you perform custom drawing. - // An empty implementation adversely affects performance during animation. - override func draw(_ rect: CGRect) { - // Drawing code + + open override func setupView() { + super.setupView() } - */ + //MARK: - MVMCoreMoleculeViewProtocol + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let progressBarModel = model as? ArrowModel else { return } + + } } From a96427b79322fb443d4d9391eb60f930e970c3bc Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 13:36:20 -0500 Subject: [PATCH 19/48] add comment --- MVMCoreUI/Utility/UIFont+FontWrapping.h | 1 + MVMCoreUI/Utility/UIFont+FontWrapping.m | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Utility/UIFont+FontWrapping.h b/MVMCoreUI/Utility/UIFont+FontWrapping.h index 1fd3360d..0302e25e 100644 --- a/MVMCoreUI/Utility/UIFont+FontWrapping.h +++ b/MVMCoreUI/Utility/UIFont+FontWrapping.h @@ -12,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN @interface UIFont (FontWrapping) +///if using mva3.0 font, should call this method to update font size. When size is bigger than 15 pt, using DS font family. Otherwise using TX font family - (UIFont *)updateFontSize:(CGFloat)size; @end diff --git a/MVMCoreUI/Utility/UIFont+FontWrapping.m b/MVMCoreUI/Utility/UIFont+FontWrapping.m index a3fa2429..8eedbb01 100644 --- a/MVMCoreUI/Utility/UIFont+FontWrapping.m +++ b/MVMCoreUI/Utility/UIFont+FontWrapping.m @@ -21,7 +21,6 @@ } else { return [self fontWithSize:size]; } - } @end From 1fa8cfd16ab750358e1d03aed16096be7a838e0e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 26 Feb 2020 13:39:44 -0500 Subject: [PATCH 20/48] opening up funcs --- MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift | 6 +++--- MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift | 4 ++-- MVMCoreUI/Atoms/Buttons/Link/Link.swift | 8 ++++---- MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift index b8026f99..d6374d78 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift @@ -14,13 +14,13 @@ open class ExternalLink: Link { // MARK: - Properties //-------------------------------------------------- - private var exportImageView: UIImageView? + public var exportImageView: UIImageView? //-------------------------------------------------- // MARK: - ModelMoleculeViewProtocol //-------------------------------------------------- - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ExternalLinkModel else { return } @@ -32,7 +32,7 @@ open class ExternalLink: Link { // MARK: - MVMCoreViewProtocol //-------------------------------------------------- - public override func setupView() { + open override func setupView() { super.setupView() let image = MVMCoreUIUtility.imageNamed("externalLink") diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift index 070e501e..f492a546 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift @@ -8,9 +8,9 @@ import UIKit -public class ExternalLinkModel: LinkModel { +open class ExternalLinkModel: LinkModel { - override public class var identifier: String { + override open class var identifier: String { return "externalLink" } } diff --git a/MVMCoreUI/Atoms/Buttons/Link/Link.swift b/MVMCoreUI/Atoms/Buttons/Link/Link.swift index a0e2583c..05d19454 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/Link.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/Link.swift @@ -40,7 +40,7 @@ import UIKit // MARK: - ModelMoleculeViewProtocol //-------------------------------------------------- - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? LinkModel else { return } @@ -60,7 +60,7 @@ import UIKit // MARK: - MVMCoreViewProtocol extension Link { - public override func updateView(_ size: CGFloat) { + open override func updateView(_ size: CGFloat) { super.updateView(size) DispatchQueue.main.async { [weak self] in guard let self = self else { return } @@ -72,7 +72,7 @@ extension Link { } } - public override func setupView() { + open override func setupView() { super.setupView() backgroundColor = .clear contentMode = .redraw @@ -88,7 +88,7 @@ extension Link { // MARK: - MVMCoreUIViewConstrainingProtocol extension Link: MVMCoreUIViewConstrainingProtocol { - public func horizontalAlignment() -> UIStackView.Alignment { + open func horizontalAlignment() -> UIStackView.Alignment { return .leading } } diff --git a/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift index 5a58decd..6e7fc83d 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift @@ -8,7 +8,7 @@ import UIKit -public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { +open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- From 10e4711c9075d003db0d497803d553779ff2a357 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 26 Feb 2020 13:44:17 -0500 Subject: [PATCH 21/48] wipppp --- MVMCoreUI/Atoms/Views/Arrow.swift | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Arrow.swift b/MVMCoreUI/Atoms/Views/Arrow.swift index 2103d73f..96f2bb9a 100644 --- a/MVMCoreUI/Atoms/Views/Arrow.swift +++ b/MVMCoreUI/Atoms/Views/Arrow.swift @@ -9,15 +9,24 @@ import UIKit open class Arrow: View { - + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- open override func setupView() { super.setupView() } - - //MARK: - MVMCoreMoleculeViewProtocol + + //-------------------------------------------------- + // MARK: - MVMCoreMoleculeViewProtocol + //-------------------------------------------------- + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let progressBarModel = model as? ArrowModel else { return } - + guard let model = model as? ArrowModel else { return } + } } From 6efbd196a876a1814663b048c6d67751b425b110 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 14:02:26 -0500 Subject: [PATCH 22/48] add error log --- MVMCoreUI/Utility/MFFonts.m | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 964707a0..0a73fb36 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -10,6 +10,7 @@ #import #import "MVMCoreUIUtility.h" @import MVMCore.MVMCoreLoggingHandler; +@import MVMCore.MVMCoreErrorConstants; NSString * const DSBold = @"VerizonNHGeDS-Bold"; NSString * const DSRegular = @"VerizonNHGeDS-Regular"; @@ -48,19 +49,27 @@ NSString * const TXRegular = @"VerizonNHGeTX-Regular"; } + (nonnull UIFont *)mfFontDSBold:(CGFloat)size { - return [UIFont fontWithName:DSBold size:size]; + UIFont *font = [UIFont fontWithName:DSBold size:size]; + [self validFont:font fontName:DSBold]; + return font ?: [UIFont boldSystemFontOfSize:size]; } + (nonnull UIFont *)mfFontDSRegular:(CGFloat)size { - return [UIFont fontWithName:DSRegular size:size]; + UIFont *font = [UIFont fontWithName:DSRegular size:size]; + [self validFont:font fontName:DSRegular]; + return font ?: [UIFont systemFontOfSize:size]; } + (nonnull UIFont *)mfFontTXBold:(CGFloat)size { - return [UIFont fontWithName:TXBold size:size]; + UIFont *font = [UIFont fontWithName:TXBold size:size]; + [self validFont:font fontName:TXBold]; + return font ?: [UIFont boldSystemFontOfSize:size]; } + (nonnull UIFont *)mfFontTXRegular:(CGFloat)size { - return [UIFont fontWithName:TXRegular size:size]; + UIFont *font = [UIFont fontWithName:TXRegular size:size]; + [self validFont:font fontName:TXRegular]; + return font ?: [UIFont systemFontOfSize:size]; } @@ -72,7 +81,7 @@ NSString * const TXRegular = @"VerizonNHGeTX-Regular"; } else { font = [self mfFontTXBold:size]; } - return font ?: [UIFont boldSystemFontOfSize:size]; + return font; } + (UIFont *)mfFont55Rg:(CGFloat)size { @@ -83,16 +92,26 @@ NSString * const TXRegular = @"VerizonNHGeTX-Regular"; } else { font = [self mfFontTXRegular:size]; } - return font ?: [UIFont systemFontOfSize:size]; + return font; } + (nullable UIFont *)mfFontOcratxt:(CGFloat)size { [self loadMVMFonts]; - return [UIFont fontWithName:@"OCRAExtended" size:size]; + UIFont *font = [UIFont fontWithName:@"OCRAExtended" size:size]; + [self validFont:font fontName:@"OCRAExtended"]; + return font; } + (UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size { - return [UIFont fontWithName:name size:size] ?: [self mfFont55Rg:size]; + UIFont *font = [UIFont fontWithName:name size:size]; + [self validFont:font fontName:name]; + return font ?: [self mfFont55Rg:size]; } ++ (void)validFont:(UIFont *)font fontName:(NSString *)fontName { + if (font == nil) { + MVMCoreErrorObject *errorObject = [[MVMCoreErrorObject alloc] initWithTitle:@"font can not load" message:[NSString stringWithFormat:@"missing font name is %@", fontName] code:ErrorCodeFontNotFound domain:ErrorDomainNative location:@"MFStyler"]; + [MVMCoreLoggingHandler addErrorToLog:errorObject]; + } +} @end From a9bec2df9c07210b651592bec7989d9fde22b726 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 26 Feb 2020 17:45:02 -0500 Subject: [PATCH 23/48] radio model --- MVMCoreUI.xcodeproj/project.pbxproj | 12 ++++++++---- MVMCoreUI/Atoms/Views/RadioButton.swift | 14 +++++++++++--- MVMCoreUI/Atoms/Views/RadioButtonModel.swift | 17 +++++++++++++++++ MVMCoreUI/FormUIHelpers/FormValidator.swift | 2 +- ...l.swift => RadioButtonSelectionHelper.swift} | 10 +++++----- .../OtherHandlers/MoleculeObjectMapping.swift | 6 ++---- 6 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 MVMCoreUI/Atoms/Views/RadioButtonModel.swift rename MVMCoreUI/Molecules/{RadioButtonModel.swift => RadioButtonSelectionHelper.swift} (84%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 95bd45b6..1f09a870 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -12,9 +12,10 @@ 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618A224BBE7700E1557D /* FormValidator.swift */; }; 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; }; 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; }; - 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */; }; + 0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */; }; 011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */; }; 011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */; }; + 011D95AF2407266E000E3791 /* RadioButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95AE2407266E000E3791 /* RadioButtonModel.swift */; }; 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */; }; 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */; }; 012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88B0238C880100FE3DA1 /* CarouselPagingModelProtocol.swift */; }; @@ -355,9 +356,10 @@ 0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = ""; }; 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = ""; }; 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = ""; }; - 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = ""; }; + 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonSelectionHelper.swift; sourceTree = ""; }; 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemModelProtocol.swift; sourceTree = ""; }; 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDownListItemModel.swift; sourceTree = ""; }; + 011D95AE2407266E000E3791 /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = ""; }; 012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModelProtocol.swift; sourceTree = ""; }; 012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateProtocol.swift; sourceTree = ""; }; 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselModel.swift; sourceTree = ""; }; @@ -1151,7 +1153,7 @@ D2A514662213885800345BFB /* MoleculeHeaderView.swift */, 012A88EB238F084D00FE3DA1 /* FooterModel.swift */, D274CA322236A78900B01B62 /* FooterView.swift */, - 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */, + 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */, 012A88C5238DA34000FE3DA1 /* ModuleMoleculeModel.swift */, D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */, @@ -1308,6 +1310,7 @@ 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */, 0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */, + 011D95AE2407266E000E3791 /* RadioButtonModel.swift */, D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */, 943784F3236B77BB006A1E82 /* GraphView.swift */, 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */, @@ -1664,7 +1667,7 @@ D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */, AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, - 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */, + 0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */, 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */, @@ -1786,6 +1789,7 @@ D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */, 017BEB7B236763000024EF95 /* LineModel.swift in Sources */, 94C2D9A523872C350006CF46 /* LabelAttributeFontModel.swift in Sources */, + 011D95AF2407266E000E3791 /* RadioButtonModel.swift in Sources */, 017BEB7F23676E870024EF95 /* MoleculeObjectMapping.swift in Sources */, D274CA332236A78900B01B62 /* FooterView.swift in Sources */, D29DF2BF21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/RadioButton.swift b/MVMCoreUI/Atoms/Views/RadioButton.swift index 23588a4c..ac579b23 100644 --- a/MVMCoreUI/Atoms/Views/RadioButton.swift +++ b/MVMCoreUI/Atoms/Views/RadioButton.swift @@ -32,7 +32,7 @@ import UIKit return json?.optionalStringForKey("radioGroupName") ?? json?.optionalStringForKey("fieldKey") }() - lazy var radioButtonModel: RadioButtonModel? = { + lazy var radioButtonModel: RadioButtonSelectionHelper? = { [unowned self] in if let radioGroupName = radioGroupName, let radioButtonModel = delegateObject?.formValidationProtocol?.formValidatorModel?()?.radioButtonsModelByGroup[radioGroupName] { @@ -98,6 +98,14 @@ import UIKit accessibilityTraits = .button accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") } + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? RadioButtonModel else { + return + } + setWithJSON(model.toJSON(), delegateObject: delegateObject, additionalData: additionalData) + } } // MARK: - MVMCoreUIViewConstrainingProtocol @@ -123,11 +131,11 @@ extension RadioButton { isRequired = jsonDictionary.boolForKey("required") self.delegateObject = delegateObject - let radioButtonModel = RadioButtonModel.setupForRadioButtonGroup(radioButton: self, + let radioButtonModel = RadioButtonSelectionHelper.setupForRadioButtonGroup(radioButton: self, formValidator: delegateObject?.formValidationProtocol?.formValidatorModel?()) FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formValidationProtocol) } - + public override func reset() { super.reset() backgroundColor = .white diff --git a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift new file mode 100644 index 00000000..3150212d --- /dev/null +++ b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift @@ -0,0 +1,17 @@ +// +// RadioButtonModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/26/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + + +public class RadioButtonModel: MoleculeModelProtocol { + public static var identifier: String = "radioButton" + public var backgroundColor: Color? + public var state: Bool = true + public var fieldKey: String? +} diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 8cb3d774..cff26347 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -16,7 +16,7 @@ import MVMCore weak var delegate: FormValidationProtocol? var fieldMolecules: [FormValidationFormFieldProtocol] = [] var enableDisableMolecules: [FormValidationEnableDisableProtocol] = [] - var radioButtonsModelByGroup: [String: RadioButtonModel] = [:] + var radioButtonsModelByGroup: [String: RadioButtonSelectionHelper] = [:] public func insertMolecule(_ molecule: FormValidationProtocol) { if let molecule = molecule as? FormValidationFormFieldProtocol { diff --git a/MVMCoreUI/Molecules/RadioButtonModel.swift b/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift similarity index 84% rename from MVMCoreUI/Molecules/RadioButtonModel.swift rename to MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift index bb70dec7..f20ac3b2 100644 --- a/MVMCoreUI/Molecules/RadioButtonModel.swift +++ b/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift @@ -9,18 +9,18 @@ import Foundation import UIKit -@objcMembers public class RadioButtonModel: NSObject { +@objcMembers public class RadioButtonSelectionHelper: NSObject { private var selectedRadioButton: RadioButton? private var fieldGroupName: String? - public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonModel { + public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonSelectionHelper { guard let groupName = radioButton.radioGroupName, let formValidator = formValidator else { - return RadioButtonModel() + return RadioButtonSelectionHelper() } - let radioButtonModel = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonModel() + let radioButtonModel = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonSelectionHelper() radioButtonModel.fieldGroupName = radioButton.formFieldGroupName() formValidator.radioButtonsModelByGroup[groupName] = radioButtonModel return radioButtonModel @@ -34,7 +34,7 @@ import UIKit } // MARK: - FormValidationFormFieldProtocol -extension RadioButtonModel: FormValidationFormFieldProtocol { +extension RadioButtonSelectionHelper: FormValidationFormFieldProtocol { public func formFieldGroupName() -> String? { return selectedRadioButton?.formFieldGroupName() ?? self.fieldGroupName } diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 30efb2f7..74383529 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -50,14 +50,13 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Toggle.self, viewModelClass: ToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CheckboxLabel.self, viewModelClass: CheckboxLabelModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self) // Horizontal Combination Molecules MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) - - + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) // Vertical Combination Molecules MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self) @@ -106,7 +105,6 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(DateDropdownEntryField.self, forKey: "dateDropdownEntryField" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(Checkbox.self, forKey: "checkbox" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(CheckboxLabel.self, forKey: "checkboxLabel" as NSString) - MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(RadioButton.self, forKey: "radioButton" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(RadioButtonLabel.self, forKey: "radioButtonLabel" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(MVMCoreUIPageControl.self, forKey: "barsPager" as NSString) From 4d209d88691bacaf9fc3430488cefffc63759afd Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 27 Feb 2020 09:28:00 -0500 Subject: [PATCH 24/48] optinal --- MVMCoreUI/Atoms/Views/RadioButtonModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift index 3150212d..b061e35e 100644 --- a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift +++ b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift @@ -12,6 +12,6 @@ import Foundation public class RadioButtonModel: MoleculeModelProtocol { public static var identifier: String = "radioButton" public var backgroundColor: Color? - public var state: Bool = true + public var state: Bool? public var fieldKey: String? } From b6af3ced00202d9ec31ad62981792b048615a010 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 27 Feb 2020 10:12:43 -0500 Subject: [PATCH 25/48] latest state --- MVMCoreUI/Atoms/Views/Arrow.swift | 66 +++++++++++++++++++ MVMCoreUI/Atoms/Views/ArrowModel.swift | 10 +-- .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Arrow.swift b/MVMCoreUI/Atoms/Views/Arrow.swift index 96f2bb9a..59e6f6f9 100644 --- a/MVMCoreUI/Atoms/Views/Arrow.swift +++ b/MVMCoreUI/Atoms/Views/Arrow.swift @@ -13,12 +13,72 @@ open class Arrow: View { // MARK: - Properties //-------------------------------------------------- + var arrowLayer = CAShapeLayer() + var lineWidth: CGFloat = 1 + var color: UIColor = .black + //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- open override func setupView() { super.setupView() + + heightAnchor.constraint(equalToConstant: 12).isActive = true + widthAnchor.constraint(equalToConstant: 12).isActive = true + + drawShapeLayer() + isOpaque = false + layer.addSublayer(arrowLayer) + arrowLayer.strokeEnd = 1 + } + + override open func layoutSubviews() { + super.layoutSubviews() + + drawShapeLayer() +// layer.cornerRadius = isRound ? cornerRadiusValue : 0 + } + + //-------------------------------------------------- + // MARK: - Drawing + //-------------------------------------------------- + + private func drawShapeLayer() { + + arrowLayer.frame = bounds + arrowLayer.strokeColor = color.cgColor + arrowLayer.fillColor = UIColor.clear.cgColor + arrowLayer.path = arrowPath() + arrowLayer.lineJoin = .miter + arrowLayer.lineCap = .butt + arrowLayer.lineWidth = lineWidth + } + + private func arrowPath() -> CGPath { + + let length = max(bounds.size.height, bounds.size.width) - 1 +// let xInsetLeft = length * 0.25 +// let yInsetTop = length * 0.3 +// let innerWidth = length - (xInsetLeft + length * 0.25) // + Right X Inset +// let innerHeight = length - (yInsetTop + length * 0.35) // + Bottom Y Inset + + var startPoint = CGPoint(x: length * 0.5, y: 1) + let pivotPoint = CGPoint(x: length, y: length * 0.5) + var endPoint = CGPoint(x: length * 0.5, y: length) + + let bezierPath = UIBezierPath() + bezierPath.move(to: startPoint) + bezierPath.addLine(to: pivotPoint) + bezierPath.addLine(to: endPoint) + + startPoint = CGPoint(x: 1, y: length * 0.5) + endPoint = CGPoint(x: length, y: length * 0.5) + + bezierPath.move(to: startPoint) + bezierPath.addLine(to: pivotPoint) + + return bezierPath.cgPath } //-------------------------------------------------- @@ -28,5 +88,11 @@ open class Arrow: View { public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let model = model as? ArrowModel else { return } + arrowLayer.transform = CATransform3DIdentity + + if let degrees = model.direction { + let radians = CGFloat(degrees * Double.pi / 180) + arrowLayer.transform = CATransform3DMakeRotation(-radians, 0.0, 0.0, 1.0) + } } } diff --git a/MVMCoreUI/Atoms/Views/ArrowModel.swift b/MVMCoreUI/Atoms/Views/ArrowModel.swift index 00e85cfb..62bf5c05 100644 --- a/MVMCoreUI/Atoms/Views/ArrowModel.swift +++ b/MVMCoreUI/Atoms/Views/ArrowModel.swift @@ -16,8 +16,8 @@ open class ArrowModel: MoleculeModelProtocol { public static var identifier: String = "arrow" public var backgroundColor: Color? - public var color: Color = Color(uiColor: .mfLighterGray()) - public var direction: Bool? + public var color: Color = Color(uiColor: .mvmBlack) + public var direction: Double? //-------------------------------------------------- // MARK: - Keys @@ -28,6 +28,7 @@ open class ArrowModel: MoleculeModelProtocol { case backgroundColor case color case direction + case size } //-------------------------------------------------- @@ -36,12 +37,13 @@ open class ArrowModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) { self.color = color } - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - direction = try typeContainer.decodeIfPresent(Bool.self, forKey: .direction) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + direction = try typeContainer.decodeIfPresent(Double.self, forKey: .direction) } public func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index ac7375d7..8cabfa3f 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -50,6 +50,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Toggle.self, viewModelClass: ToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CheckboxLabel.self, viewModelClass: CheckboxLabelModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Arrow.self, viewModelClass: ArrowModel.self) // Horizontal Combination Molecules MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) From 207d1915d53e0b9eae6a36e51c44abd9a052fda2 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Thu, 27 Feb 2020 21:37:02 +0530 Subject: [PATCH 26/48] Added ListLeftVariableRadioButtonAndPaymentMethod molecule. --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++ ...tVariableRadioButtonAndPaymentMethod.swift | 53 +++++++++++++++++++ ...ableRadioButtonAndPaymentMethodModel.swift | 47 ++++++++++++++++ .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 4 files changed, 109 insertions(+) create mode 100644 MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift create mode 100644 MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index d9401e4d..95a73635 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -104,6 +104,8 @@ 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; }; 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; }; 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */; }; + 52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */; }; + 52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */; }; 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; }; 8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */; }; 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; }; @@ -444,6 +446,8 @@ 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = ""; }; 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = ""; }; 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDividerModel.swift; sourceTree = ""; }; + 52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAndPaymentMethod.swift; sourceTree = ""; }; + 52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAndPaymentMethodModel.swift; sourceTree = ""; }; 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = ""; }; 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaretModel.swift; sourceTree = ""; }; 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = ""; }; @@ -1036,6 +1040,8 @@ D22B38EB23F4E0AE00490EF6 /* LeftVariable */ = { isa = PBXGroup; children = ( + 52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */, + 52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */, 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */, 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */, 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, @@ -1746,6 +1752,7 @@ 012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */, D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, + 52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */, D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */, 014AA73123C5059B006F3E93 /* ListPageTemplateModel.swift in Sources */, 017BEB4023620A230024EF95 /* TextFieldModel.swift in Sources */, @@ -1885,6 +1892,7 @@ D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */, D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */, 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */, + 52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */, D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */, 0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */, 94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */, diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift new file mode 100644 index 00000000..7667340c --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift @@ -0,0 +1,53 @@ +// +// ListLeftVariableRadioButtonAndPaymentMethod.swift +// MVMCoreUI +// +// Created by Kruthika KP on 27/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers open class ListLeftVariableRadioButtonAndPaymentMethod: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //------------------------------------------------------- + let radioButton = RadioButton(frame: .zero) + let leftImage = MFLoadImageView(pinnedEdges: .all) + let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink() + let stack = Stack(frame: .zero) + + //----------------------------------------------------- + // MARK: - View Lifecycle + //------------------------------------------------------- + override open func setupView() { + super.setupView() + stack.stackItems = [StackItem(andContain: radioButton), + StackItem(andContain: leftImage), + StackItem(andContain: eyebrowHeadlineBodyLink)] + addMolecule(stack) + } + //---------------------------------------------------- + // MARK: - Molecule + //----------------------------------------------------- + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? ListLeftVariableRadioButtonAndPaymentMethodModel else { return} + radioButton.setWithModel(model.radioButton, delegateObject, additionalData) + leftImage.setWithModel(model.image, delegateObject, additionalData) + eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + + // Create a stack model to use for the internal stack and set the alignment of labels + let stackModel = StackModel(molecules: [StackItemModel(percent:10,horizontalAlignment: .center), + StackItemModel(percent:10,horizontalAlignment: .fill), + StackItemModel(percent:80,horizontalAlignment: .leading)], + axis: .horizontal) + stack.model = stackModel + stack.restack() + } + + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 90 + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift new file mode 100644 index 00000000..e7b41635 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift @@ -0,0 +1,47 @@ +// +// ListLeftVariableRadioButtonAndPaymentMethodModel.swift +// MVMCoreUI +// +// Created by Kruthika KP on 27/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListLeftVariableRadioButtonAndPaymentMethodModel: ListItemModel, MoleculeModelProtocol { + public static var identifier: String = "listLVRBImg" + public var radioButton : RadioButtonModel + public var image: ImageViewModel + public var eyebrowHeadlineBodyLink : EyebrowHeadlineBodyLinkModel + + public init(radioButton: RadioButtonModel, image: ImageViewModel, eyebrowHeadlineBodyLink:EyebrowHeadlineBodyLinkModel) { + self.radioButton = radioButton + self.image = image + self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink + super.init() + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case radioButton + case image + case eyebrowHeadlineBodyLink + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + radioButton = try typeContainer.decode(RadioButtonModel.self, forKey: .radioButton) + image = try typeContainer.decode(ImageViewModel.self, forKey: .image) + eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(radioButton, forKey: .radioButton) + try container.encode(image, forKey: .image) + try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) + } +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 6550c6f5..db741f53 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -77,6 +77,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableIconWithRightCaret.self, viewModelClass: ListLeftVariableIconWithRightCaretModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self) // List items MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: MoleculeListItemModel.self) From 5640129cdfe779595c8a130f4165372303694496 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 27 Feb 2020 11:44:24 -0500 Subject: [PATCH 27/48] working state of arrow --- MVMCoreUI/Atoms/Views/Arrow.swift | 66 +++++++++++--------------- MVMCoreUI/Atoms/Views/ArrowModel.swift | 21 +++++--- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Arrow.swift b/MVMCoreUI/Atoms/Views/Arrow.swift index 59e6f6f9..7e1a510a 100644 --- a/MVMCoreUI/Atoms/Views/Arrow.swift +++ b/MVMCoreUI/Atoms/Views/Arrow.swift @@ -14,8 +14,10 @@ open class Arrow: View { //-------------------------------------------------- var arrowLayer = CAShapeLayer() - var lineWidth: CGFloat = 1 - var color: UIColor = .black + + public var arrowModel: ArrowModel? { + return model as? ArrowModel + } //-------------------------------------------------- // MARK: - Lifecycle @@ -24,8 +26,8 @@ open class Arrow: View { open override func setupView() { super.setupView() - heightAnchor.constraint(equalToConstant: 12).isActive = true - widthAnchor.constraint(equalToConstant: 12).isActive = true + heightAnchor.constraint(equalToConstant: 40).isActive = true + widthAnchor.constraint(equalToConstant: 40).isActive = true drawShapeLayer() isOpaque = false @@ -33,66 +35,54 @@ open class Arrow: View { arrowLayer.strokeEnd = 1 } - override open func layoutSubviews() { - super.layoutSubviews() - - drawShapeLayer() -// layer.cornerRadius = isRound ? cornerRadiusValue : 0 - } - //-------------------------------------------------- // MARK: - Drawing //-------------------------------------------------- + open override func draw(_ rect: CGRect) { + super.draw(rect) + + arrowLayer.transform = CATransform3DIdentity + drawShapeLayer() + + if let degrees = arrowModel?.degrees { + let radians = CGFloat(degrees * Float.pi / 180) + arrowLayer.transform = CATransform3DMakeRotation(-radians, 0.0, 0.0, 1.0) + } + } + private func drawShapeLayer() { arrowLayer.frame = bounds - arrowLayer.strokeColor = color.cgColor + arrowLayer.strokeColor = arrowModel?.color.cgColor arrowLayer.fillColor = UIColor.clear.cgColor arrowLayer.path = arrowPath() arrowLayer.lineJoin = .miter arrowLayer.lineCap = .butt - arrowLayer.lineWidth = lineWidth + arrowLayer.lineWidth = arrowModel?.lineWidth ?? 1 } private func arrowPath() -> CGPath { - let length = max(bounds.size.height, bounds.size.width) - 1 -// let xInsetLeft = length * 0.25 -// let yInsetTop = length * 0.3 -// let innerWidth = length - (xInsetLeft + length * 0.25) // + Right X Inset -// let innerHeight = length - (yInsetTop + length * 0.35) // + Bottom Y Inset + let length = max(bounds.size.height, bounds.size.width) + let inset = (arrowModel?.lineWidth ?? 1) / 2 + let midLength = length / 2 - var startPoint = CGPoint(x: length * 0.5, y: 1) - let pivotPoint = CGPoint(x: length, y: length * 0.5) - var endPoint = CGPoint(x: length * 0.5, y: length) + var startPoint = CGPoint(x: midLength, y: inset) + let pivotPoint = CGPoint(x: length - inset, y: midLength) + var endPoint = CGPoint(x: midLength, y: length - inset) let bezierPath = UIBezierPath() bezierPath.move(to: startPoint) bezierPath.addLine(to: pivotPoint) bezierPath.addLine(to: endPoint) - startPoint = CGPoint(x: 1, y: length * 0.5) - endPoint = CGPoint(x: length, y: length * 0.5) + startPoint = CGPoint(x: inset, y: midLength) + endPoint = CGPoint(x: length - inset, y: midLength) bezierPath.move(to: startPoint) bezierPath.addLine(to: pivotPoint) return bezierPath.cgPath } - - //-------------------------------------------------- - // MARK: - MVMCoreMoleculeViewProtocol - //-------------------------------------------------- - - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let model = model as? ArrowModel else { return } - - arrowLayer.transform = CATransform3DIdentity - - if let degrees = model.direction { - let radians = CGFloat(degrees * Double.pi / 180) - arrowLayer.transform = CATransform3DMakeRotation(-radians, 0.0, 0.0, 1.0) - } - } } diff --git a/MVMCoreUI/Atoms/Views/ArrowModel.swift b/MVMCoreUI/Atoms/Views/ArrowModel.swift index 62bf5c05..926a9ea7 100644 --- a/MVMCoreUI/Atoms/Views/ArrowModel.swift +++ b/MVMCoreUI/Atoms/Views/ArrowModel.swift @@ -17,7 +17,8 @@ open class ArrowModel: MoleculeModelProtocol { public var backgroundColor: Color? public var color: Color = Color(uiColor: .mvmBlack) - public var direction: Double? + public var degrees: Float = 0 + public var lineWidth: CGFloat = 1 //-------------------------------------------------- // MARK: - Keys @@ -27,8 +28,9 @@ open class ArrowModel: MoleculeModelProtocol { case moleculeName case backgroundColor case color - case direction + case degrees case size + case lineWidth } //-------------------------------------------------- @@ -37,20 +39,27 @@ open class ArrowModel: MoleculeModelProtocol { 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 } - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - direction = try typeContainer.decodeIfPresent(Double.self, forKey: .direction) + if let degrees = try typeContainer.decodeIfPresent(Float.self, forKey: .degrees) { + self.degrees = degrees + } + + if let lineWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .lineWidth) { + self.lineWidth = lineWidth + } } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(color, forKey: .color) - try container.encode(direction, forKey: .direction) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encode(color, forKey: .color) + try container.encode(degrees, forKey: .degrees) + try container.encodeIfPresent(backgroundColor, forKey: .lineWidth) } } From 78673b824ecc128b7ba89db36dbc87f0fc556048 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 27 Feb 2020 11:46:17 -0500 Subject: [PATCH 28/48] removed test code --- MVMCoreUI/Atoms/Views/Arrow.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Arrow.swift b/MVMCoreUI/Atoms/Views/Arrow.swift index 7e1a510a..7ae112cc 100644 --- a/MVMCoreUI/Atoms/Views/Arrow.swift +++ b/MVMCoreUI/Atoms/Views/Arrow.swift @@ -26,9 +26,6 @@ open class Arrow: View { open override func setupView() { super.setupView() - heightAnchor.constraint(equalToConstant: 40).isActive = true - widthAnchor.constraint(equalToConstant: 40).isActive = true - drawShapeLayer() isOpaque = false layer.addSublayer(arrowLayer) From 1ee8c244cd15a3f704658b6eea17ea7a108e0837 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 27 Feb 2020 11:57:10 -0500 Subject: [PATCH 29/48] merging --- MVMCoreUI/Atoms/Views/Arrow.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MVMCoreUI/Atoms/Views/Arrow.swift b/MVMCoreUI/Atoms/Views/Arrow.swift index 7ae112cc..e59b4022 100644 --- a/MVMCoreUI/Atoms/Views/Arrow.swift +++ b/MVMCoreUI/Atoms/Views/Arrow.swift @@ -26,6 +26,9 @@ open class Arrow: View { open override func setupView() { super.setupView() + heightAnchor.constraint(equalToConstant: 12).isActive = true + widthAnchor.constraint(equalToConstant: 12).isActive = true + drawShapeLayer() isOpaque = false layer.addSublayer(arrowLayer) From c2baebe4831eb84e14dfde88b5572050aa85192a Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 27 Feb 2020 12:00:45 -0500 Subject: [PATCH 30/48] removed testing code --- MVMCoreUI/Atoms/Views/Arrow.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Arrow.swift b/MVMCoreUI/Atoms/Views/Arrow.swift index e59b4022..7ae112cc 100644 --- a/MVMCoreUI/Atoms/Views/Arrow.swift +++ b/MVMCoreUI/Atoms/Views/Arrow.swift @@ -26,9 +26,6 @@ open class Arrow: View { open override func setupView() { super.setupView() - heightAnchor.constraint(equalToConstant: 12).isActive = true - widthAnchor.constraint(equalToConstant: 12).isActive = true - drawShapeLayer() isOpaque = false layer.addSublayer(arrowLayer) From 6c92652f01cad6a7c618425f3da4b7072c294bff Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 27 Feb 2020 12:31:47 -0500 Subject: [PATCH 31/48] moved files --- MVMCoreUI.xcodeproj/project.pbxproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index f33d39b2..5c92c180 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -94,10 +94,10 @@ 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; }; 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; }; 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; }; - 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; }; - 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; }; 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BAE23FEF956004C5109 /* ExternalLink.swift */; }; 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */; }; + 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; }; + 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; }; 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; }; 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; }; 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; }; @@ -435,10 +435,10 @@ 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = ""; }; 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = ""; }; 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = ""; }; - 0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = ""; }; - 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = ""; }; 0AE98BAE23FEF956004C5109 /* ExternalLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalLink.swift; sourceTree = ""; }; 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalLinkModel.swift; sourceTree = ""; }; + 0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = ""; }; + 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = ""; }; 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = ""; }; 31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = ""; }; 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = ""; }; @@ -1341,8 +1341,8 @@ 0AA33B392398524F0067DD0F /* Toggle.swift */, D260105423CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift */, 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */, - 0AE98BB423FF18D2004C5109 /* Arrow.swift */, 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */, + 0AE98BB423FF18D2004C5109 /* Arrow.swift */, ); path = Views; sourceTree = ""; From e7b7012708b9f69150938871606d82cd78172188 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 27 Feb 2020 13:00:39 -0500 Subject: [PATCH 32/48] constraint convenience --- MVMCoreUI/Atoms/Views/Arrow.swift | 15 +++++++++++++++ MVMCoreUI/Atoms/Views/ArrowModel.swift | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/MVMCoreUI/Atoms/Views/Arrow.swift b/MVMCoreUI/Atoms/Views/Arrow.swift index 7ae112cc..e932dd60 100644 --- a/MVMCoreUI/Atoms/Views/Arrow.swift +++ b/MVMCoreUI/Atoms/Views/Arrow.swift @@ -19,6 +19,21 @@ open class Arrow: View { return model as? ArrowModel } + //-------------------------------------------------- + // MARK: - Constraints + //-------------------------------------------------- + + public var heightConstraint: NSLayoutConstraint? + public var widthConstraint: NSLayoutConstraint? + + public func pinHeightAndWidth(constant: CGFloat = 12) { + + heightConstraint = heightAnchor.constraint(equalToConstant: constant) + widthConstraint = widthAnchor.constraint(equalToConstant: constant) + heightConstraint?.isActive = true + widthConstraint?.isActive = true + } + //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- diff --git a/MVMCoreUI/Atoms/Views/ArrowModel.swift b/MVMCoreUI/Atoms/Views/ArrowModel.swift index 926a9ea7..2547f8d1 100644 --- a/MVMCoreUI/Atoms/Views/ArrowModel.swift +++ b/MVMCoreUI/Atoms/Views/ArrowModel.swift @@ -20,6 +20,9 @@ open class ArrowModel: MoleculeModelProtocol { public var degrees: Float = 0 public var lineWidth: CGFloat = 1 + public var height: CGFloat = 12 + public var width: CGFloat = 12 + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- @@ -31,6 +34,8 @@ open class ArrowModel: MoleculeModelProtocol { case degrees case size case lineWidth + case height + case width } //-------------------------------------------------- @@ -52,6 +57,14 @@ open class ArrowModel: MoleculeModelProtocol { if let lineWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .lineWidth) { self.lineWidth = lineWidth } + + if let height = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .height) { + self.lineWidth = height + } + + if let width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width) { + self.width = width + } } public func encode(to encoder: Encoder) throws { @@ -61,5 +74,7 @@ open class ArrowModel: MoleculeModelProtocol { try container.encode(color, forKey: .color) try container.encode(degrees, forKey: .degrees) try container.encodeIfPresent(backgroundColor, forKey: .lineWidth) + try container.encode(width, forKey: .width) + try container.encode(height, forKey: .height) } } From 0b6fe7059aa624b53546e9749b283c8150a20777 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 27 Feb 2020 13:45:15 -0500 Subject: [PATCH 33/48] Cleanup for names and stack --- MVMCoreUI.xcodeproj/project.pbxproj | 2 +- MVMCoreUI/Atoms/Buttons/CaretLink.swift | 4 +- MVMCoreUI/Atoms/Buttons/Link.swift | 6 +- MVMCoreUI/Atoms/Buttons/PillButton.swift | 8 +- ...maryButton+MoleculeProtocolExtension.swift | 2 +- .../TextFields/BaseDropdownEntryField.swift | 6 +- .../TextFields/DateDropdownEntryField.swift | 4 +- .../Atoms/TextFields/DigitEntryField.swift | 4 +- MVMCoreUI/Atoms/TextFields/EntryField.swift | 6 +- .../TextFields/ItemDropdownEntryField.swift | 4 +- .../MFTextField+ModelExtension.swift | 2 +- .../Atoms/TextFields/TextEntryField.swift | 4 +- MVMCoreUI/Atoms/Views/CaretView.swift | 6 +- MVMCoreUI/Atoms/Views/Checkbox.swift | 6 +- MVMCoreUI/Atoms/Views/CheckboxLabel.swift | 6 +- MVMCoreUI/Atoms/Views/DashLine.swift | 6 +- MVMCoreUI/Atoms/Views/GraphView.swift | 6 +- MVMCoreUI/Atoms/Views/Label/Label.swift | 2 +- .../Views/Label/LabelAttributeModel.swift | 2 +- .../Atoms/Views/LeftRightLabelView.swift | 9 +- MVMCoreUI/Atoms/Views/Line.swift | 4 +- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 2 +- .../Atoms/Views/MFView+ModelExtension.swift | 6 +- .../Atoms/Views/MVMCoreUISwitch+Model.swift | 2 +- MVMCoreUI/Atoms/Views/MultiProgress.swift | 6 +- MVMCoreUI/Atoms/Views/ProgressBar.swift | 4 +- MVMCoreUI/Atoms/Views/Toggle.swift | 4 +- MVMCoreUI/BaseClasses/Button.swift | 12 +-- MVMCoreUI/BaseClasses/Control.swift | 12 +-- MVMCoreUI/BaseClasses/TableViewCell.swift | 16 +-- MVMCoreUI/BaseClasses/View.swift | 12 +-- .../Views/Container/Container.swift | 4 +- .../Views/EntryFieldContainer.swift | 4 +- .../Containers/Views/MoleculeContainer.swift | 26 ++--- .../ModelProtocols/FormModelProtocol.swift | 2 +- .../MoleculeModelProtocol.swift | 2 +- .../TemplateModelProtocol.swift | 2 +- ...tLeftVariableCheckboxAllTextAndLinks.swift | 38 ++++--- .../ListLeftVariableIconWithRightCaret.swift | 41 ++++--- ...neColumnFullWidthTextAllTextAndLinks.swift | 74 +++++++++++++ ...umnFullWidthTextAllTextAndLinksModel.swift | 0 .../List/RightVariable/ListRVWheel.swift | 38 ++++--- .../ListRightVariablePayments.swift | 34 +++--- ...neColumnFullWidthTextAllTextAndLinks.swift | 66 ------------ .../ListThreeColumnPlanDataDivider.swift | 39 +++---- .../Molecules/Doughnut/DoughnutChart.swift | 8 +- .../Doughnut/DoughnutChartView.swift | 20 ++-- .../ImageHeadlineBody.swift | 10 +- .../TwoButtonView.swift | 15 +-- .../Items/DropDownFilterTableViewCell.swift | 12 +-- .../Items/MoleculeCollectionViewCell.swift | 8 +- .../Items/MoleculeTableViewCell.swift | 16 +-- .../Molecules/Items/TabsTableViewCell.swift | 6 +- .../ActionDetailWithImage.swift | 10 +- .../LeftRightViews/CornerLabels.swift | 14 +-- .../HeadlineBodyLinkToggle.swift | 13 +-- .../ToggleMolecules/HeadlineBodyToggle.swift | 12 +-- .../ToggleMolecules/LabelToggle.swift | 14 +-- .../Molecules/ModelMoleculeViewProtocol.swift | 22 ++-- MVMCoreUI/Molecules/ModuleMolecule.swift | 20 ++-- MVMCoreUI/Molecules/MoleculeHeaderView.swift | 6 +- MVMCoreUI/Molecules/Scroller.swift | 6 +- .../EyebrowHeadlineBodyLink.swift | 35 +++--- .../HeadLineBodyCaretLinkImage.swift | 12 +-- .../HeadlineBody.swift | 10 +- .../HeadlineBodyButton.swift | 10 +- .../HeadlineBodyLink.swift | 10 +- .../StringAndMoleculeStack.swift | 4 +- .../StringAndMoleculeView.swift | 6 +- MVMCoreUI/Organisms/Carousel.swift | 8 +- MVMCoreUI/Organisms/MoleculeStackView.swift | 2 +- MVMCoreUI/Organisms/Stack.swift | 102 ++++++++++++++---- MVMCoreUI/Organisms/StackModel.swift | 12 ++- ...MoleculeMappingObject+ModelExtension.swift | 4 +- .../Templates/MoleculeListTemplate.swift | 6 +- .../Templates/MoleculeStackTemplate.swift | 2 +- 76 files changed, 542 insertions(+), 438 deletions(-) create mode 100644 MVMCoreUI/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift rename MVMCoreUI/Molecules/DesignedComponents/{SectionDividers => List}/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift (100%) delete mode 100644 MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 95bd45b6..e6188bbd 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -1004,6 +1004,7 @@ D22B38EA23F4E08B00490EF6 /* List */ = { isa = PBXGroup; children = ( + 52267A0523FFE0A900906CBA /* OneColumn */, AA4FC2A323F4F69600E251DB /* RightVariable */, D22B38EB23F4E0AE00490EF6 /* LeftVariable */, ); @@ -1024,7 +1025,6 @@ D22B38EC23F4E10700490EF6 /* SectionDividers */ = { isa = PBXGroup; children = ( - 52267A0523FFE0A900906CBA /* OneColumn */, D22B38ED23F4E11100490EF6 /* ThreeColumn */, ); path = SectionDividers; diff --git a/MVMCoreUI/Atoms/Buttons/CaretLink.swift b/MVMCoreUI/Atoms/Buttons/CaretLink.swift index ca665928..50eb7f83 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretLink.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretLink.swift @@ -125,7 +125,7 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { setTitleColor(disabledColor, for: .disabled) } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let caretLinkModel = model as? CaretLinkModel else { return } if let color = caretLinkModel.backgroundColor { backgroundColor = color.uiColor @@ -147,7 +147,7 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { return .leading } - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 10.5 } } diff --git a/MVMCoreUI/Atoms/Buttons/Link.swift b/MVMCoreUI/Atoms/Buttons/Link.swift index 5dbbed16..f22931b7 100644 --- a/MVMCoreUI/Atoms/Buttons/Link.swift +++ b/MVMCoreUI/Atoms/Buttons/Link.swift @@ -40,8 +40,8 @@ import UIKit // MARK: - ModelMoleculeViewProtocol //-------------------------------------------------- - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? LinkModel else { return } setTitle(model.title, for: .normal) setTitleColor(model.textColor.uiColor, for: .normal) @@ -50,7 +50,7 @@ import UIKit set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 31.0 } } diff --git a/MVMCoreUI/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atoms/Buttons/PillButton.swift index d3d09cee..d7fa8db5 100644 --- a/MVMCoreUI/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atoms/Buttons/PillButton.swift @@ -119,9 +119,9 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol, FormValidation } // MARK: - ModelMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { // The button will get styled in the enable check in super. - super.setWithModel(model, delegateObject, additionalData) + super.set(with: model, delegateObject, additionalData) guard let model = model as? ButtonModel else { return } setTitle(model.title, for: .normal) @@ -132,8 +132,8 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol, FormValidation } } - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - PillButton.getHeight(for: (molecule as? ButtonModel)?.size, size: MVMCoreUIUtility.getWidth()) + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + PillButton.getHeight(for: (model as? ButtonModel)?.size, size: MVMCoreUIUtility.getWidth()) } // MARK: - MVMCoreViewProtocol diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift index 39b015ae..b161472c 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift @@ -10,7 +10,7 @@ import Foundation // temporary until link is finished extension PrimaryButton: ModelMoleculeViewProtocol { - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let model = model as? ButtonModel else { return } setTitle(model.title, for: .normal) backgroundColor = model.backgroundColor?.uiColor diff --git a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift index 70b46866..b7c59fd5 100644 --- a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift @@ -69,12 +69,12 @@ import UIKit dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? BaseDropdownEntryFieldModel else { return } - dropDownCaretView.setWithModel(model.caretView, delegateObject, additionalData) + dropDownCaretView.setOptional(with: model.caretView, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift index acfe0a42..95174096 100644 --- a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift @@ -111,8 +111,8 @@ import UIKit setTextWith(date: datePicker?.date) } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? DateDropdownEntryFieldModel else { return } diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift index 9febf0c1..53181bff 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift @@ -328,7 +328,7 @@ import UIKit } } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let model = model as? DigitEntryFieldModel else { return } @@ -341,7 +341,7 @@ import UIKit MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: delegateObject as? UITextFieldDelegate) } - super.setWithModel(model, delegateObject, additionalData) + super.set(with: model, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atoms/TextFields/EntryField.swift index 82cc69f6..bbea1c62 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryField.swift @@ -240,13 +240,13 @@ import UIKit entryFieldContainer.reset() } - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) self.delegateObject = delegateObject guard let model = model as? EntryFieldModel else { return } - entryFieldContainer.setWithModel(model, delegateObject, additionalData) + entryFieldContainer.set(with: model, delegateObject, additionalData) title = model.title feedback = model.feedback diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift index 48728ce9..0ecfc4ad 100644 --- a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift @@ -95,8 +95,8 @@ open class ItemDropdownEntryField: BaseDropdownEntryField { } } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? ItemDropdownEntryFieldModel else { return } diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift b/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift index a077c285..e57cec9c 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift +++ b/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift @@ -16,7 +16,7 @@ enum TextType: String { } extension MFTextField: ModelMoleculeViewProtocol { // - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { //TODO: Need to create setWithModel in ViewConstraining View #warning("This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.") //TODO: This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView. diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index 67721f27..61f6c82c 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -277,8 +277,8 @@ import UIKit resignFirstResponder() } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? TextEntryFieldModel else { return } diff --git a/MVMCoreUI/Atoms/Views/CaretView.swift b/MVMCoreUI/Atoms/Views/CaretView.swift index 26573af5..fff56f82 100644 --- a/MVMCoreUI/Atoms/Views/CaretView.swift +++ b/MVMCoreUI/Atoms/Views/CaretView.swift @@ -184,12 +184,12 @@ open class CaretView: View { public override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { guard let json = json, let model = try? Self.decodeJSONToModel(json: json, type: CaretViewModel.self) else { return } - setWithModel(model, delegateObject, additionalData) + set(with: model, delegateObject, additionalData) } //MARK: - MVMCoreMoleculeViewProtocol - override public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + override public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let caretModel = model as? CaretViewModel else { return } diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index 27bed31e..fd186d7e 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -395,7 +395,7 @@ import MVMCore heightConstraint?.constant = dimension } - layoutIfNeeded() + //layoutIfNeeded() } public override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { @@ -456,8 +456,8 @@ import MVMCore } } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? CheckboxModel else { return } diff --git a/MVMCoreUI/Atoms/Views/CheckboxLabel.swift b/MVMCoreUI/Atoms/Views/CheckboxLabel.swift index 700cbd4f..72429aa2 100644 --- a/MVMCoreUI/Atoms/Views/CheckboxLabel.swift +++ b/MVMCoreUI/Atoms/Views/CheckboxLabel.swift @@ -115,15 +115,15 @@ } } - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let checkBoxWithLabelModel = model as? CheckboxLabelModel else { return } if let checkboxAlignment = checkBoxWithLabelModel.checkboxAlignment { alignCheckbox(checkboxAlignment) } - checkbox.setWithModel(checkBoxWithLabelModel.checkbox, delegateObject, additionalData) - label.setWithModel(checkBoxWithLabelModel.label, delegateObject, additionalData) + checkbox.set(with: checkBoxWithLabelModel.checkbox, delegateObject, additionalData) + label.set(with: checkBoxWithLabelModel.label, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Atoms/Views/DashLine.swift b/MVMCoreUI/Atoms/Views/DashLine.swift index fc8f8bc3..63b28dbd 100644 --- a/MVMCoreUI/Atoms/Views/DashLine.swift +++ b/MVMCoreUI/Atoms/Views/DashLine.swift @@ -89,12 +89,12 @@ open class DashLine: View { open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { guard let json = json, let model = try? Self.decodeJSONToModel(json: json, type: DashLineModel.self) else { return } - setWithModel(model, delegateObject, additionalData) + set(with: model, delegateObject, additionalData) } //MARK: - MVMCoreMoleculeViewProtocol - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let dashLineModel = dashModel else { return } diff --git a/MVMCoreUI/Atoms/Views/GraphView.swift b/MVMCoreUI/Atoms/Views/GraphView.swift index 12f2fca8..997c58d0 100644 --- a/MVMCoreUI/Atoms/Views/GraphView.swift +++ b/MVMCoreUI/Atoms/Views/GraphView.swift @@ -26,8 +26,8 @@ import UIKit widthAnchor.constraint(equalTo: heightAnchor).isActive = true } - override open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? CircleProgressModel else { return } createGraphCircle(model) rotationAnimation(model) @@ -35,7 +35,7 @@ import UIKit override open func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { guard let json = json, let model = try? Self.decodeJSONToModel(json: json, type: CircleProgressModel.self) else { return } - setWithModel(model, delegateObject, additionalData) + set(with: model, delegateObject, additionalData) } class func getAngle(_ piValue: Double) -> Double { diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index f08d532d..3a99fa00 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -219,7 +219,7 @@ public typealias ActionBlock = () -> () case left } - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { clauses = [] diff --git a/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift index 437ec0cc..ddc468b7 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers open class LabelAttributeModel: Model { +@objcMembers open class LabelAttributeModel: ModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- diff --git a/MVMCoreUI/Atoms/Views/LeftRightLabelView.swift b/MVMCoreUI/Atoms/Views/LeftRightLabelView.swift index 1096df37..d8cebb51 100644 --- a/MVMCoreUI/Atoms/Views/LeftRightLabelView.swift +++ b/MVMCoreUI/Atoms/Views/LeftRightLabelView.swift @@ -179,13 +179,14 @@ import Foundation //MARK: - MVMCoreMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + 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 } - leftTextLabel.setWithModel(leftRightLabelModel.leftText, delegateObject, additionalData) - rightTextLabel.setWithModel(leftRightLabelModel.rightText, delegateObject, additionalData) + leftTextLabel.set(with: leftRightLabelModel.leftText, delegateObject, additionalData) + rightTextLabel.setOptional(with: leftRightLabelModel.rightText, delegateObject, additionalData) + if !leftTextLabel.hasText { constrainRightLabel() } else if !rightTextLabel.hasText { diff --git a/MVMCoreUI/Atoms/Views/Line.swift b/MVMCoreUI/Atoms/Views/Line.swift index d6ec5d8a..37bf5688 100644 --- a/MVMCoreUI/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atoms/Views/Line.swift @@ -67,11 +67,11 @@ import UIKit super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) } - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { if let lineModel = model as? LineModel { setStyle(lineModel.type ?? .standard) } - super.setWithModel(model, delegateObject, additionalData) + super.set(with: model, delegateObject, additionalData) } open override func reset() { diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index 0079d1a6..e61a5af3 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -209,7 +209,7 @@ import UIKit } } - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.delegateObject = delegateObject // TODO: Temporary, should be moved to init once we have type erasure ready. setAsMolecule() diff --git a/MVMCoreUI/Atoms/Views/MFView+ModelExtension.swift b/MVMCoreUI/Atoms/Views/MFView+ModelExtension.swift index d532d7c4..af14bc44 100644 --- a/MVMCoreUI/Atoms/Views/MFView+ModelExtension.swift +++ b/MVMCoreUI/Atoms/Views/MFView+ModelExtension.swift @@ -9,16 +9,16 @@ import Foundation extension MFView { - public func setUpDefaultWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public func setUpDefaultWithModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.model = model - if let backgroundColor = model?.backgroundColor { + if let backgroundColor = model.backgroundColor { self.backgroundColor = backgroundColor.uiColor } } } extension ModelMoleculeViewProtocol where Self: MFView { - func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { setUpDefaultWithModel(model, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift index e2ef7b31..aeccf2ff 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift +++ b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift @@ -10,7 +10,7 @@ import Foundation // temporary until link is finished extension MVMCoreUISwitch: ModelMoleculeViewProtocol { - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let model = model as? ToggleModel else { return } if let castSelf = self as? FormValidationProtocol { diff --git a/MVMCoreUI/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atoms/Views/MultiProgress.swift index cd05ed0b..02be560c 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgress.swift @@ -64,8 +64,8 @@ import UIKit } //MARK: - MVMCoreMoleculeViewProtocol - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let multiProgressModel = multiProgressModel else { return } @@ -83,6 +83,6 @@ import UIKit public override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { guard let json = json, let model = try? Self.decodeJSONToModel(json: json, type: MultiProgressBarModel.self) else { return } - setWithModel(model, delegateObject, additionalData) + set(with: model, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Atoms/Views/ProgressBar.swift b/MVMCoreUI/Atoms/Views/ProgressBar.swift index 17d35c29..3f302135 100644 --- a/MVMCoreUI/Atoms/Views/ProgressBar.swift +++ b/MVMCoreUI/Atoms/Views/ProgressBar.swift @@ -51,7 +51,7 @@ import Foundation } //MARK: - MVMCoreMoleculeViewProtocol - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let progressBarModel = model as? ProgressBarModel else { return } @@ -66,7 +66,7 @@ import Foundation // MARK: - MVMCoreUIMoleculeViewProtocol public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { guard let json = json, let model = try? Self.decodeJSONToModel(json: json, type: ProgressBarModel.self) else { return } - setWithModel(model, delegateObject, additionalData) + set(with: model, delegateObject, additionalData) } public func reset() { diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index 80425054..ee888b3f 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -334,7 +334,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) } // MARK:- ModelMoleculeViewProtocol - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let toggleModel = model as? ToggleModel else { return } @@ -343,7 +343,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) setWithJSON(toggleModelJSON, delegateObject: delegateObject, additionalData: additionalData) } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return Self.getContainerHeight() } } diff --git a/MVMCoreUI/BaseClasses/Button.swift b/MVMCoreUI/BaseClasses/Button.swift index c0ff0e81..8722b800 100644 --- a/MVMCoreUI/BaseClasses/Button.swift +++ b/MVMCoreUI/BaseClasses/Button.swift @@ -87,10 +87,10 @@ public typealias ButtonAction = (Button) -> () } // MARK:- ModelMoleculeViewProtocol - open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.model = model - if let backgroundColor = model?.backgroundColor { + if let backgroundColor = model.backgroundColor { self.backgroundColor = backgroundColor.uiColor } @@ -100,15 +100,15 @@ public typealias ButtonAction = (Button) -> () set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } - open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - return model?.moleculeName + open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + return model.moleculeName } - open class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return nil } - open class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { return nil } } diff --git a/MVMCoreUI/BaseClasses/Control.swift b/MVMCoreUI/BaseClasses/Control.swift index d73e0fef..265e56b3 100644 --- a/MVMCoreUI/BaseClasses/Control.swift +++ b/MVMCoreUI/BaseClasses/Control.swift @@ -48,22 +48,22 @@ import UIKit } // MARK:- ModelMoleculeViewProtocol - open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.model = model - if let backgroundColor = model?.backgroundColor { + if let backgroundColor = model.backgroundColor { self.backgroundColor = backgroundColor.uiColor } } - open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - return model?.moleculeName + open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + return model.moleculeName } - open class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return nil } - open class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { return nil } } diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index d96a4587..b546ad2c 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -150,8 +150,8 @@ import UIKit contentView.preservesSuperviewLayoutMargins = false } - //TODO: Model, Change to model - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + //TODO: ModelProtocol, Change to model + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let model = model as? ListItemModelProtocol else { return } self.listItemModel = model @@ -169,7 +169,7 @@ import UIKit // override the separator if let separator = model.line { addSeparatorsIfNeeded() - bottomSeparatorView?.setWithModel(separator, nil, nil) + bottomSeparatorView?.set(with: separator, nil, nil) } if let moleculeModel = model as? MoleculeModelProtocol, @@ -183,11 +183,11 @@ import UIKit backgroundColor = .white } - public class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - return model?.moleculeName + public class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + return model.moleculeName } - public class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return nil } @@ -246,8 +246,8 @@ import UIKit public func setLines(with model: LineModel?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?, indexPath: IndexPath) { addSeparatorsIfNeeded() if let model = model { - topSeparatorView?.setWithModel(model, delegateObject, additionalData) - bottomSeparatorView?.setWithModel(model, delegateObject, additionalData) + topSeparatorView?.set(with: model, delegateObject, additionalData) + bottomSeparatorView?.set(with: model, delegateObject, additionalData) } else { topSeparatorView?.setStyle(.standard) bottomSeparatorView?.setStyle(.standard) diff --git a/MVMCoreUI/BaseClasses/View.swift b/MVMCoreUI/BaseClasses/View.swift index a117d60a..860ce442 100644 --- a/MVMCoreUI/BaseClasses/View.swift +++ b/MVMCoreUI/BaseClasses/View.swift @@ -40,22 +40,22 @@ import UIKit } // MARK:- ModelMoleculeViewProtocol - open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.model = model - if let backgroundColor = model?.backgroundColor { + if let backgroundColor = model.backgroundColor { self.backgroundColor = backgroundColor.uiColor } } - open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - return model?.moleculeName + open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + return model.moleculeName } - open class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return nil } - open class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { return nil } } diff --git a/MVMCoreUI/Containers/Views/Container/Container.swift b/MVMCoreUI/Containers/Views/Container/Container.swift index 53abfda3..96e6c3e8 100644 --- a/MVMCoreUI/Containers/Views/Container/Container.swift +++ b/MVMCoreUI/Containers/Views/Container/Container.swift @@ -16,8 +16,8 @@ open class Container: View, ContainerProtocol { } // MARK:- ModelMoleculeViewProtocol - override open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let containerModel = model as? ContainerModelProtocol else { return } containerHelper.set(with: containerModel, for: view as? MVMCoreUIViewConstrainingProtocol) } diff --git a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift index 3f80006a..773721f7 100644 --- a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift +++ b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift @@ -276,8 +276,8 @@ import UIKit // MARK: - MVMCoreUIMoleculeViewProtocol //-------------------------------------------------- - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) self.delegateObject = delegateObject } } diff --git a/MVMCoreUI/Containers/Views/MoleculeContainer.swift b/MVMCoreUI/Containers/Views/MoleculeContainer.swift index d179ef72..f98451dd 100644 --- a/MVMCoreUI/Containers/Views/MoleculeContainer.swift +++ b/MVMCoreUI/Containers/Views/MoleculeContainer.swift @@ -30,40 +30,40 @@ open class MoleculeContainer: Container { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { if let casteModel = model as? MoleculeContainerModelProtocol { if view != nil { - (view as? ModelMoleculeViewProtocol)?.setWithModel(casteModel.molecule, delegateObject, additionalData) + (view as? ModelMoleculeViewProtocol)?.set(with: casteModel.molecule, delegateObject, additionalData) } else { if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(casteModel.molecule, delegateObject) { addMolecule(molecule) } } } - super.setWithModel(model, delegateObject, additionalData) + super.set(with: model, delegateObject, additionalData) } - public override static func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + public override static func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { guard let containerModel = model as? MoleculeContainerModelProtocol, let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(containerModel.molecule) as? ModelMoleculeViewProtocol.Type, - let moleculeName = moleculeClass.nameForReuse(containerModel.molecule, delegateObject) else { - return "\(model?.moleculeName ?? "moleculeContainer")<>" + let moleculeName = moleculeClass.nameForReuse(with: containerModel.molecule, delegateObject) else { + return "\(model.moleculeName ?? "moleculeContainer")<>" } - return "\(model?.moleculeName ?? "moleculeContainer")<\(moleculeName)>" + return "\(model.moleculeName ?? "moleculeContainer")<\(moleculeName)>" } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - guard let containerModel = molecule as? MoleculeContainerModelProtocol else { return 0 } + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let containerModel = model as? MoleculeContainerModelProtocol else { return 0 } guard let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(containerModel.molecule) as? ModelMoleculeViewProtocol.Type, - let moleculeHeight = moleculeClass.estimatedHeight(forRow: containerModel.molecule, delegateObject: delegateObject) else { + let moleculeHeight = moleculeClass.estimatedHeight(with: containerModel.molecule, delegateObject) else { return (containerModel.topMarginPadding ?? 0) + (containerModel.bottomMarginPadding ?? 0) } return moleculeHeight + (containerModel.topMarginPadding ?? 0) + (containerModel.bottomMarginPadding ?? 0) } - public override class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let containerModel = molecule as? MoleculeContainerModelProtocol, + public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let containerModel = model as? MoleculeContainerModelProtocol, let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(containerModel.molecule) as? ModelMoleculeViewProtocol.Type else { return nil } - return moleculeClass.requiredModules(containerModel.molecule, delegateObject: delegateObject, error: error) + return moleculeClass.requiredModules(with: containerModel.molecule, delegateObject, error: error) } } diff --git a/MVMCoreUI/Models/ModelProtocols/FormModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/FormModelProtocol.swift index 1224d5a9..28840f06 100644 --- a/MVMCoreUI/Models/ModelProtocols/FormModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/FormModelProtocol.swift @@ -9,7 +9,7 @@ import Foundation -public protocol FormModelProtocol: Model { +public protocol FormModelProtocol: ModelProtocol { var required: Bool? { get } var fieldKey: String? { get } var groupName: String? { get } diff --git a/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift index cec7b90a..2928cf2a 100644 --- a/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift @@ -1,7 +1,7 @@ import Foundation -public protocol MoleculeModelProtocol: Model { +public protocol MoleculeModelProtocol: ModelProtocol { var moleculeName: String? { get } var backgroundColor: Color? { get set } } diff --git a/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift index 793baa0a..3ed37d6b 100644 --- a/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift @@ -9,7 +9,7 @@ import Foundation -public protocol TemplateModelProtocol: PageModelProtocol, Model { +public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol { var template: String { get } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift index 0dad7228..8d7fb539 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift @@ -11,30 +11,36 @@ import Foundation @objcMembers open class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell { public let checkbox = Checkbox(frame: .zero) public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) - public let stack = Stack(frame: .zero) + public var stack: Stack + + // MARK: - Initializers + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: checkbox, model: StackItemModel(horizontalAlignment: .fill)), + (view: eyebrowHeadlineBodyLink, model: StackItemModel(horizontalAlignment: .leading))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } // MARK: - View Lifecycle override open func setupView() { super.setupView() - stack.stackItems = [StackItem(andContain: checkbox),StackItem(andContain: eyebrowHeadlineBodyLink)] addMolecule(stack) - } - - // MARK:- MVMCoreUIMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) - guard let model = model as? ListLeftVariableCheckboxAllTextAndLinksModel else { return} - checkbox.setWithModel(model.checkbox, delegateObject, additionalData) - eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) - - let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill), - StackItemModel(horizontalAlignment: .leading)], - axis: .horizontal) - stack.model = stackModel stack.restack() } - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + // MARK:- MVMCoreUIMoleculeViewProtocol + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListLeftVariableCheckboxAllTextAndLinksModel else { return} + checkbox.set(with: model.checkbox, delegateObject, additionalData) + eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 140 } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift index 058d0da3..670624ad 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift @@ -17,39 +17,46 @@ import UIKit let leftImage = MFLoadImageView(pinnedEdges: .all) let leftLabel = Label.commonLabelB2(true) let rightLabel = Label.commonLabelB2(true) - let stack = Stack(frame: .zero) + var stack: Stack + + //----------------------------------------------------- + // MARK: - Initializers + //----------------------------------------------------- + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: leftImage, model: StackItemModel(horizontalAlignment: .fill)), + (view: leftLabel, model: StackItemModel(horizontalAlignment: .fill)), + (view: rightLabel, model: StackItemModel(spacing: 4, horizontalAlignment: .trailing))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } //----------------------------------------------------- // MARK: - View Lifecycle //------------------------------------------------------- - override open func setupView() { super.setupView() - stack.stackItems = [StackItem(andContain: leftImage),StackItem(andContain: leftLabel),StackItem(andContain: rightLabel)] - addMolecule(stack) leftLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal) rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal) + addMolecule(stack) + stack.restack() } //---------------------------------------------------- // MARK: - Molecule //------------------------------------------------------ - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? ListLeftVariableIconWithRightCaretModel else { return} - leftImage.setWithModel(model.image, delegateObject, additionalData) - leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) - rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) - - let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill), - StackItemModel(horizontalAlignment: .fill), - StackItemModel(horizontalAlignment: .trailing)], - axis: .horizontal) - stack.model = stackModel - stack.restack() + leftImage.set(with: model.image, delegateObject, additionalData) + leftLabel.set(with: model.leftLabel, delegateObject, additionalData) + rightLabel.set(with: model.rightLabel, delegateObject, additionalData) } - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 90 } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift new file mode 100644 index 00000000..1ea1a4a9 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -0,0 +1,74 @@ +// +// ListOneColumnFullWidthTextAllTextAndLinks.swift +// MVMCoreUI +// +// Created by Kruthika KP on 14/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class ListOneColumnFullWidthTextAllTextAndLinks: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //----------------------------------------------------- + var stack: Stack + let eyebrow = Label.commonLabelB3(true) + let headline = Label.commonLabelH3(true) + let subHeadline = Label.commonLabelB1(true) + let body = Label.commonLabelB2(true) + let link = Link() + + //----------------------------------------------------- + // MARK: - Initializers + //----------------------------------------------------- + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [eyebrow, headline, subHeadline, body, link]) + stack.stackModel?.spacing = 0 + stack.stackModel?.molecules[4].spacing = 2 + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //----------------------------------------------------- + // MARK: - View Lifecycle + //----------------------------------------------------- + override open func setupView() { + super.setupView() + addMolecule(stack) + } + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){ + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return } + eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData) + headline.setOptional(with: model.headline, delegateObject, additionalData) + subHeadline.setOptional(with: model.subHeadline, delegateObject, additionalData) + body.setOptional(with: model.body, delegateObject, additionalData) + link.setOptional(with: model.link, delegateObject, additionalData) + + // Hide labels if neeeded. + stack.stackModel?.molecules[0].gone = !eyebrow.hasText + stack.stackModel?.molecules[1].gone = !headline.hasText + stack.stackModel?.molecules[2].gone = !subHeadline.hasText + stack.stackModel?.molecules[3].gone = !body.hasText + stack.stackModel?.molecules[4].gone = (link.titleLabel?.text?.count ?? 0) == 0 + stack.restack() + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 90 + } + + open override func reset() { + super.reset() + eyebrow.styleB3(true) + headline.styleH3(true) + subHeadline.styleB1(true) + body.styleB2(true) + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift similarity index 100% rename from MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift rename to MVMCoreUI/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift index 46d4b955..5ad5d182 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift @@ -11,7 +11,22 @@ import Foundation let wheel = GraphView(frame: .zero) let leftLabel = Label.commonLabelB1(true) let rightLabel = Label.commonLabelB2(true) - let stack = Stack(frame: .zero) + var stack: Stack + + //----------------------------------------------------- + // MARK: - Initializers + //----------------------------------------------------- + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: leftLabel, model: StackItemModel(horizontalAlignment: .leading)), + (view: wheel, model: StackItemModel(horizontalAlignment: .fill)), + (view: rightLabel, model: StackItemModel(spacing: 4, horizontalAlignment: .fill))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } //------------------------------------------------- // MARK: - Setup @@ -19,26 +34,19 @@ import Foundation open override func setupView() { super.setupView() rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) - stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: wheel),StackItem(andContain: rightLabel)] addMolecule(stack) + stack.restack() } //------------------------------------------------- // MARK: - ModelMoleculeViewProtocol //------------------------------------------------- - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? ListRVWheelModel else { return } - leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) - rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) - wheel.setWithModel(model.wheel, delegateObject, additionalData) - - let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading), - StackItemModel(horizontalAlignment: .fill), - StackItemModel(spacing: 4, horizontalAlignment: .fill)], - axis: .horizontal) - stack.model = stackModel - stack.restack() + leftLabel.set(with: model.leftLabel, delegateObject, additionalData) + rightLabel.set(with: model.rightLabel, delegateObject, additionalData) + wheel.set(with: model.wheel, delegateObject, additionalData) } //------------------------------------------------- @@ -50,7 +58,7 @@ import Foundation rightLabel.styleB2(true) } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 70 } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 66f88371..9cfccd04 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -15,34 +15,42 @@ import Foundation //------------------------------------------------------- let leftLabel = Label.commonLabelB1(true) let rightImage = MFLoadImageView(pinnedEdges: .all) - let stack = Stack(frame: .zero) + var stack: Stack + + //----------------------------------------------------- + // MARK: - Initializers + //----------------------------------------------------- + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: leftLabel, model: StackItemModel(horizontalAlignment: .leading)), + (view: rightImage, model: StackItemModel(horizontalAlignment: .fill))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } //----------------------------------------------------- // MARK: - View Lifecycle //------------------------------------------------------- override open func setupView() { super.setupView() - stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)] addMolecule(stack) + stack.restack() } //---------------------------------------------------- // MARK: - Molecule //------------------------------------------------------ - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? ListRightVariablePaymentsModel else { return } - leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) - rightImage.setWithModel(model.image, delegateObject, additionalData) - - let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading), - StackItemModel(horizontalAlignment: .fill)], - axis: .horizontal) - stack.model = stackModel - stack.restack() + leftLabel.set(with: model.leftLabel, delegateObject, additionalData) + rightImage.set(with: model.image, delegateObject, additionalData) } - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 65 } diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift deleted file mode 100644 index 6f0ed557..00000000 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// ListOneColumnFullWidthTextAllTextAndLinks.swift -// MVMCoreUI -// -// Created by Kruthika KP on 14/02/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -@objcMembers public class ListOneColumnFullWidthTextAllTextAndLinks: TableViewCell { - - //----------------------------------------------------- - // MARK: - Outlets - //----------------------------------------------------- - - let stack = Stack(frame: .zero) - let eyebrow = Label.commonLabelB3(true) - let headline = Label.commonLabelH3(true) - let subHeadline = Label.commonLabelB1(true) - let body = Label.commonLabelB2(true) - let link = Link() - - //----------------------------------------------------- - // MARK: - View Lifecycle - //------------------------------------------------------- - override open func setupView() { - super.setupView() - stack.stackItems = [StackItem(andContain: eyebrow), - StackItem(andContain: headline), - StackItem(andContain: subHeadline), - StackItem(andContain: body), - StackItem(andContain: link)] - addMolecule(stack) - } - - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){ - super.setWithModel(model, delegateObject, additionalData) - guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return } - eyebrow.setWithModel(model.eyebrow, delegateObject, additionalData) - headline.setWithModel(model.headline, delegateObject, additionalData) - subHeadline.setWithModel(model.subHeadline, delegateObject, additionalData) - body.setWithModel(model.body, delegateObject, additionalData) - link.setWithModel(model.link, delegateObject, additionalData) - let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText), - StackItemModel(gone: !headline.hasText), - StackItemModel(gone: !subHeadline.hasText), - StackItemModel(gone: !body.hasText), - StackItemModel(spacing: 2, gone: (link.titleLabel?.text?.count ?? 0) == 0)], - spacing: 0) - stack.model = stackModel - stack.restack() - } - - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return 90 - } - - open override func reset() { - super.reset() - eyebrow.styleB3(true) - headline.styleH3(true) - subHeadline.styleB1(true) - body.styleB2(true) - } -} diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift index 565ed737..9adbe531 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift @@ -13,35 +13,38 @@ import Foundation let leftHeadlineBody = HeadlineBody(frame: .zero) let centerHeadLineBody = HeadlineBody(frame: .zero) let rightHeadLineBody = HeadlineBody(frame: .zero) - let stack = Stack(frame: .zero) + var stack: Stack + + // MARK: - Initializers + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: leftHeadlineBody, model: StackItemModel(percent: 33, horizontalAlignment: .leading)), + (view: centerHeadLineBody, model: StackItemModel(percent: 34, horizontalAlignment: .center)), + (view: rightHeadLineBody, model: StackItemModel(percent: 33, horizontalAlignment: .trailing))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } // MARK: - MFViewProtocol open override func setupView() { super.setupView() - - //using stackItems to align the three headlineBody - stack.stackItems = [StackItem(andContain: leftHeadlineBody),StackItem(andContain: centerHeadLineBody),StackItem(andContain: rightHeadLineBody)] addMolecule(stack) + stack.restack() } // MARK: - MVMCoreUIMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? ListThreeColumnPlanDataDividerModel else { return } - leftHeadlineBody.setWithModel(model.leftHeadlineBody, delegateObject, additionalData) - centerHeadLineBody.setWithModel(model.centerHeadlineBody, delegateObject, additionalData) - rightHeadLineBody.setWithModel(model.rightHeadlineBody, delegateObject, additionalData) - - // Create a stack model to use for the internal stack and set the alignment of models - let stackModel = StackModel(molecules: [StackItemModel(percent: 33, horizontalAlignment: .leading), - StackItemModel(percent: 34, horizontalAlignment: .center), - StackItemModel(percent: 33, horizontalAlignment: .trailing)], - axis: .horizontal) - stack.model = stackModel - stack.restack() + leftHeadlineBody.set(with: model.leftHeadlineBody, delegateObject, additionalData) + centerHeadLineBody.set(with: model.centerHeadlineBody, delegateObject, additionalData) + rightHeadLineBody.set(with: model.rightHeadlineBody, delegateObject, additionalData) } - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { return 121 } } diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift index cbb6aeba..acaa0923 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift @@ -94,14 +94,14 @@ open class DoughnutChart: View { doughnutLayer.transform = CATransform3DMakeRotation(1 * .pi, 0.0, 0.0, 1.0) } - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) clearLayers() guard let doughnutChartModel = doughnutChartModel else { return } - titleLabel.setWithModel(doughnutChartModel.title, delegateObject, additionalData) - subTitleLabel.setWithModel(doughnutChartModel.subtitle, delegateObject, additionalData) + titleLabel.setOptional(with: doughnutChartModel.title, delegateObject, additionalData) + subTitleLabel.setOptional(with: doughnutChartModel.subtitle, delegateObject, additionalData) titleLabel.textAlignment = .center subTitleLabel.textAlignment = .center updateLabelContainer() diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift index 6bf91a43..7d279759 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift @@ -65,11 +65,11 @@ import Foundation colorLablesStack.reset() } - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = doughnutChartModel else { return } - doughnutChart.setWithModel(model, delegateObject, additionalData) + doughnutChart.set(with: model, delegateObject, additionalData) // Create the stack model var stackItems: [MoleculeStackItemModel] = [] @@ -78,12 +78,12 @@ import Foundation } let stack = MoleculeStackModel(molecules: stackItems) stack.verticalAlignment = .fill - colorLablesStack.setWithModel(stack, delegateObject, additionalData) + colorLablesStack.set(with: stack, delegateObject, additionalData) } open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { guard let json = json, let model = try? Self.decodeJSONToModel(json: json, type: DoughnutChartModel.self) else { return } - setWithModel(model, delegateObject, additionalData) + set(with: model, delegateObject, additionalData) } } @@ -94,12 +94,12 @@ extension DoughnutChartView: MVMCoreUIViewConstrainingProtocol { } class ColorViewLabelsStack: MoleculeStackView { - override func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + override func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { let view = ColorViewWithLabel() let stackItem = MoleculeStackItem(andContain: view) - stackItem.setWithModel(model, delegateObject, additionalData) + stackItem.set(with: model, delegateObject, additionalData) stackItems.append(stackItem) } } @@ -149,12 +149,12 @@ class ColorViewWithLabel: View { label.setAsMolecule() } - override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let chartItemModel = model as? DoughnutChartItemModel else { return } - label.setWithModel(chartItemModel.label, delegateObject, additionalData) + label.set(with: chartItemModel.label, delegateObject, additionalData) colorView.backgroundColor = chartItemModel.color.uiColor } } diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift index 840f4763..469b1929 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift @@ -51,14 +51,14 @@ import UIKit } // MARK:- ModelMoleculeViewProtocol - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 95 } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? ImageHeadlineBodyModel else { return } - headlineBody.setWithModel(model.headlineBody, delegateObject, additionalData) - imageView.setWithModel(model.image, delegateObject, additionalData) + headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + imageView.set(with: model.image, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index be6228f8..50288c58 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -101,23 +101,24 @@ import UIKit } // MARK: - ModelMoleculeViewProtocol - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - guard let model = molecule as? TwoButtonViewModel else { return 0 } - return PillButton.estimatedHeight(forRow: model.primaryButton ?? model.secondaryButton, delegateObject: delegateObject) + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let model = model as? TwoButtonViewModel, + let buttonModel = model.primaryButton ?? model.secondaryButton else { return 0 } + return PillButton.estimatedHeight(with: buttonModel, delegateObject) } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? TwoButtonViewModel else { return } if let secondaryModel = model.secondaryButton { showSecondaryButton() - secondaryButton.setWithModel(secondaryModel, delegateObject, additionalData) + secondaryButton.set(with: secondaryModel, delegateObject, additionalData) } else { hideSecondaryButton() } if let primaryModel = model.primaryButton { showPrimaryButton() - primaryButton.setWithModel(primaryModel, delegateObject, additionalData) + primaryButton.set(with: primaryModel, delegateObject, additionalData) } else { hidePrimaryButton() } diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index 164bd2c3..dd530605 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -44,12 +44,12 @@ import UIKit } } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - dropDownListItemModel = model as? DropDownListItemModel + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.delegateObject = delegateObject - super.setWithModel(model, delegateObject, additionalData) - - dropDown.setWithModel(dropDownListItemModel?.dropDown, delegateObject, additionalData) + super.set(with: model, delegateObject, additionalData) + if let dropDownListItemModel = model as? DropDownListItemModel { + dropDown.set(with: dropDownListItemModel.dropDown, delegateObject, additionalData) + } dropDown.observingTextFieldDelegate = delegateObject?.uiTextFieldDelegate as? ObservingTextFieldDelegate dropDown.uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate } @@ -59,7 +59,7 @@ import UIKit bottomSeparatorView?.setStyle(.none) } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 80 } } diff --git a/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift index 9d56f4cd..9c63ba64 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift @@ -68,7 +68,7 @@ open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeVi } - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let collectionModel = model as? CarouselItemModel else { return } @@ -98,7 +98,7 @@ open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeVi molecule = moleculeView } } else { - (molecule as? ModelMoleculeViewProtocol)?.setWithModel(collectionModel.molecule, delegateObject, additionalData) + (molecule as? ModelMoleculeViewProtocol)?.set(with: collectionModel.molecule, delegateObject, additionalData) } guard let molecule = molecule else { return } @@ -114,10 +114,10 @@ open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeVi backgroundColor = .white } - public class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + public class func nameForReuse(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { guard let molecule = (model as? CarouselItemModel)?.molecule, let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) as? ModelMoleculeViewProtocol.Type, - let name = moleculeClass.nameForReuse(molecule, delegateObject) ?? molecule.moleculeName else { + let name = moleculeClass.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName else { return nil } return name diff --git a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift index 0416ce8e..f1d3794b 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift @@ -13,13 +13,13 @@ import UIKit // MARK: - MVMCoreUIMoleculeViewProtocol - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? MoleculeListItemModel else { return } if molecule != nil { - (molecule as? ModelMoleculeViewProtocol)?.setWithModel(model.molecule, delegateObject, additionalData) + (molecule as? ModelMoleculeViewProtocol)?.set(with: model.molecule, delegateObject, additionalData) } else if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model.molecule, delegateObject, false) { addMolecule(moleculeView) @@ -28,11 +28,11 @@ import UIKit containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol) } - public override class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule else { return "\(self)<>" } let className = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moleculeModel) as? ModelMoleculeViewProtocol.Type - let moleculeName = className?.nameForReuse(moleculeModel, delegateObject) ?? moleculeModel.moleculeName ?? "" + let moleculeName = className?.nameForReuse(with: moleculeModel, delegateObject) ?? moleculeModel.moleculeName ?? "" return "\(self)<\(moleculeName)>" } @@ -45,10 +45,10 @@ import UIKit return theClass.requiredModules?(moleculeJSON, delegateObject: delegateObject, error: error) } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - guard let moleculeModel = (molecule as? MoleculeContainerModel)?.molecule, + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + guard let moleculeModel = (model as? MoleculeContainerModel)?.molecule, let classType = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moleculeModel) as? ModelMoleculeViewProtocol.Type, - let height = classType.estimatedHeight(forRow: moleculeModel, delegateObject: delegateObject) + let height = classType.estimatedHeight(with: moleculeModel, delegateObject) else { return 80 } return max(2 * PaddingDefaultVerticalSpacing3, height) diff --git a/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift b/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift index 8a971221..da700a28 100644 --- a/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift @@ -36,8 +36,8 @@ import UIKit // MARK: - MoleculeDelegateProtocol - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) self.delegateObject = delegateObject tabs.reloadData() } @@ -47,7 +47,7 @@ import UIKit tabs.reset() } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 46 } } diff --git a/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImage.swift b/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImage.swift index bde18777..b550ad0d 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImage.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImage.swift @@ -114,14 +114,14 @@ import UIKit } // MARK:- ModelMoleculeViewProtocol - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 197 } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? ActionDetailWithImageModel else { return } - headlineBodyButton.setWithModel(model.headlineBodyButton, delegateObject, additionalData) - imageLoader.setWithModel(model.image, delegateObject, additionalData) + headlineBodyButton.set(with: model.headlineBodyButton, delegateObject, additionalData) + imageLoader.set(with: model.image, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Molecules/LeftRightViews/CornerLabels.swift b/MVMCoreUI/Molecules/LeftRightViews/CornerLabels.swift index 2de9deca..f7ae36de 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/CornerLabels.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/CornerLabels.swift @@ -166,19 +166,19 @@ import UIKit return 34 } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? CornerLabelsModel else { return } if middleView != nil { - (middleView as? ModelMoleculeViewProtocol)?.setWithModel(model, delegateObject, additionalData) + (middleView as? ModelMoleculeViewProtocol)?.set(with: model, delegateObject, additionalData) } else if let moleculeModel = model.molecule, let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(moleculeModel, delegateObject) { addMiddleView(molecule) } - topLeftLabel.setWithModel(model.topLeftLabel, delegateObject, additionalData) - topRightLabel.setWithModel(model.topRightLabel, delegateObject, additionalData) - bottomLeftLabel.setWithModel(model.bottomLeftLabel, delegateObject, additionalData) - bottomRightLabel.setWithModel(model.bottomRightLabel, delegateObject, additionalData) + topLeftLabel.setOptional(with: model.topLeftLabel, delegateObject, additionalData) + topRightLabel.setOptional(with: model.topRightLabel, delegateObject, additionalData) + bottomLeftLabel.setOptional(with: model.bottomLeftLabel, delegateObject, additionalData) + bottomRightLabel.setOptional(with: model.bottomRightLabel, delegateObject, additionalData) topLabelToMoleculeConstraint?.constant = (middleView != nil && (topLeftLabel.hasText || topRightLabel.hasText)) ? spaceAboveMolecule : 0 bottomLabelToMoleculeConstraint?.constant = (middleView != nil && (bottomLeftLabel.hasText || bottomRightLabel.hasText)) ? spaceBelowMolecule : 0 diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggle.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggle.swift index 07639dbe..bfed52e4 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggle.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggle.swift @@ -38,15 +38,16 @@ import UIKit } // MARK:- ModelMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? HeadlineBodyLinkToggleModel else { return } - headlineBodyLink.setWithModel(model.headlineBodyLink, delegateObject, additionalData) - toggle.setWithModel(model.toggle, delegateObject, additionalData) + headlineBodyLink.set(with: model.headlineBodyLink, delegateObject, additionalData) + toggle.set(with: model.toggle, delegateObject, additionalData) } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return HeadlineBodyLink.estimatedHeight(forRow: (molecule as? HeadlineBodyLinkToggleModel)?.headlineBodyLink, delegateObject: delegateObject) + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let model = model as? HeadlineBodyLinkToggleModel else { return nil } + return HeadlineBodyLink.estimatedHeight(with: model.headlineBodyLink, delegateObject) } } diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggle.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggle.swift index 8df94fa8..bbfe0ffc 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggle.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggle.swift @@ -35,18 +35,18 @@ import UIKit } // MARK:- ModelMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let headlineBodyToggleModel = model as? HeadlineBodyToggleModel else { return } setWithJSON(headlineBodyToggleModel.toJSON(), delegateObject: delegateObject, additionalData: additionalData) } - open class override func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - guard let model = molecule as? HeadlineBodyToggleModel, - let toggleHeight = Toggle.estimatedHeight(forRow: model.toggle, delegateObject: delegateObject), - let headlineBody = HeadlineBody.estimatedHeight(forRow: model.headlineBody, delegateObject: delegateObject) else { return nil } + open class override func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let model = model as? HeadlineBodyToggleModel, + let toggleHeight = Toggle.estimatedHeight(with: model.toggle, delegateObject), + let headlineBody = HeadlineBody.estimatedHeight(with: model.headlineBody, delegateObject) else { return nil } return max(toggleHeight, headlineBody) } diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift index f2925cc9..ccbdf9c3 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift @@ -32,19 +32,19 @@ import UIKit } // MARK:- ModelMoleculeViewProtocol - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - guard let model = molecule as? LabelToggleModel, - let toggleHeight = Toggle.estimatedHeight(forRow: model.toggle, delegateObject: delegateObject), - let labelHeight = Label.estimatedHeight(forRow: model.label, delegateObject: delegateObject) else { return nil } + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let model = model as? LabelToggleModel, + let toggleHeight = Toggle.estimatedHeight(with: model.toggle, delegateObject), + let labelHeight = Label.estimatedHeight(with: model.label, delegateObject) else { return nil } return max(toggleHeight, labelHeight) } - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let labelToggleModel = model as? LabelToggleModel else { return } - label.setWithModel(labelToggleModel.label, delegateObject, additionalData) - toggle.setWithModel(labelToggleModel.toggle, delegateObject, additionalData) + label.set(with: labelToggleModel.label, delegateObject, additionalData) + toggle.set(with: labelToggleModel.toggle, delegateObject, additionalData) } // MARK: - MVMCoreUIMoleculeViewProtocol diff --git a/MVMCoreUI/Molecules/ModelMoleculeViewProtocol.swift b/MVMCoreUI/Molecules/ModelMoleculeViewProtocol.swift index 972ee175..fbeadd96 100644 --- a/MVMCoreUI/Molecules/ModelMoleculeViewProtocol.swift +++ b/MVMCoreUI/Molecules/ModelMoleculeViewProtocol.swift @@ -9,20 +9,20 @@ import Foundation public protocol ModelMoleculeViewProtocol { - func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) - static func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? - static func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? - static func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? + func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) + static func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? + static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? + static func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? } extension ModelMoleculeViewProtocol { - public static func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - return model?.moleculeName + public static func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + return model.moleculeName } - public static func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return nil } - public static func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + public static func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { return nil } // Temporary @@ -31,4 +31,10 @@ extension ModelMoleculeViewProtocol { let decoder = JSONDecoder() return try decoder.decode(type, from: data) } + + public func setOptional(with model: T?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + if let model = model { + set(with: model, delegateObject, additionalData) + } + } } diff --git a/MVMCoreUI/Molecules/ModuleMolecule.swift b/MVMCoreUI/Molecules/ModuleMolecule.swift index 360410b7..e92f41da 100644 --- a/MVMCoreUI/Molecules/ModuleMolecule.swift +++ b/MVMCoreUI/Molecules/ModuleMolecule.swift @@ -19,8 +19,8 @@ open class ModuleMolecule: Container { super.setupView() } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let moduleMoleculeModel = model as? ModuleMoleculeModel, let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMoleculeModel.moduleName) else { @@ -42,36 +42,36 @@ open class ModuleMolecule: Container { } } } else { - moduleMolecule?.setWithModel(model, delegateObject, additionalData) + moduleMolecule?.set(with: model, delegateObject, additionalData) } } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - guard let moduleMolecule = molecule as? ModuleMoleculeModel, + guard let moduleMolecule = model as? ModuleMoleculeModel, let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMolecule.moduleName), let classType = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moduleModel) as? ModelMoleculeViewProtocol.Type, - let height = classType.estimatedHeight(forRow: moduleModel, delegateObject: delegateObject)else { + let height = classType.estimatedHeight(with: moduleModel, delegateObject) else { // Critical error return 0 } return height } - public override class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { guard let moduleMolecule = model as? ModuleMoleculeModel, let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMolecule.moduleName), let classType = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moduleModel) as? ModelMoleculeViewProtocol.Type, - let name = classType.nameForReuse(moduleModel, delegateObject) else { + let name = classType.nameForReuse(with: moduleModel, delegateObject) else { // Critical error return "moduleMolecule<>" } return name } - public override class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let moduleName = (molecule as? ModuleMoleculeModel)?.moduleName, + guard let moduleName = (model as? ModuleMoleculeModel)?.moduleName, let _ = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { if let errorObject = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), code: CoreUIErrorCode.ErrorCodeModuleMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) { error?.pointee = errorObject diff --git a/MVMCoreUI/Molecules/MoleculeHeaderView.swift b/MVMCoreUI/Molecules/MoleculeHeaderView.swift index 5d58c675..3404afc3 100644 --- a/MVMCoreUI/Molecules/MoleculeHeaderView.swift +++ b/MVMCoreUI/Molecules/MoleculeHeaderView.swift @@ -37,11 +37,11 @@ public class MoleculeHeaderView: MoleculeContainer { } // MARK: - ModelMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let headerModel = headerModel else { return } if let lineModel = headerModel.line { - line.setWithModel(lineModel, delegateObject, additionalData) + line.set(with: lineModel, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Molecules/Scroller.swift b/MVMCoreUI/Molecules/Scroller.swift index 8ee77816..6184f3d0 100644 --- a/MVMCoreUI/Molecules/Scroller.swift +++ b/MVMCoreUI/Molecules/Scroller.swift @@ -29,10 +29,10 @@ import UIKit constraint.isActive = true } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { if let casteModel = model as? ScrollerModel { if view != nil { - (view as? ModelMoleculeViewProtocol)?.setWithModel(casteModel.molecule, delegateObject, additionalData) + (view as? ModelMoleculeViewProtocol)?.set(with: casteModel.molecule, delegateObject, additionalData) } else { if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(casteModel.molecule, delegateObject) { contentView.addSubview(molecule) @@ -41,6 +41,6 @@ import UIKit } } } - super.setWithModel(model, delegateObject, additionalData) + super.set(with: model, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index e9d7d34e..58fa2d00 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -8,7 +8,7 @@ import UIKit -@objcMembers open class EyebrowHeadlineBodyLink: Container { +@objcMembers open class EyebrowHeadlineBodyLink: View { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- @@ -29,10 +29,8 @@ import UIKit open override func setupView() { super.setupView() - stack.stackItems = [StackItem(andContain: eyebrow), - StackItem(andContain: headline), - StackItem(andContain: body), - StackItem(andContain: link)] + stack.setAndCreateModel(with: [eyebrow, headline, body, link]) + stack.stackModel?.spacing = 0 addSubview(stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) } @@ -49,7 +47,6 @@ import UIKit open override func reset() { super.reset() stack.reset() - stack.stackModel?.spacing = 0 eyebrow.styleB3(true) headline.styleB1(true) body.styleB2(true) @@ -59,25 +56,23 @@ import UIKit // MARK: - ModelMoleculeViewProtocol //-------------------------------------------------- - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) - eyebrow.setWithModel(casteModel?.eyebrow, delegateObject, additionalData) - headline.setWithModel(casteModel?.headline, delegateObject, additionalData) - body.setWithModel(casteModel?.body, delegateObject, additionalData) - link.setWithModel(casteModel?.link, delegateObject, additionalData) + eyebrow.setOptional(with: casteModel?.eyebrow, delegateObject, additionalData) + headline.setOptional(with: casteModel?.headline, delegateObject, additionalData) + body.setOptional(with: casteModel?.body, delegateObject, additionalData) + link.setOptional(with: casteModel?.link, delegateObject, additionalData) - // Create a stack model to use for the internal stack. - let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText), - StackItemModel(gone: !headline.hasText), - StackItemModel(gone: !body.hasText), - StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)]) - stackModel.spacing = 0 - stack.model = stackModel + // Hide labels if neeeded. + stack.stackModel?.molecules[0].gone = !eyebrow.hasText + stack.stackModel?.molecules[1].gone = !headline.hasText + stack.stackModel?.molecules[2].gone = !body.hasText + stack.stackModel?.molecules[3].gone = (link.titleLabel?.text?.count ?? 0) == 0 stack.restack() } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 65 } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadLineBodyCaretLinkImage.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadLineBodyCaretLinkImage.swift index 2b3567d7..00ccaeeb 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadLineBodyCaretLinkImage.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadLineBodyCaretLinkImage.swift @@ -73,17 +73,17 @@ import Foundation } // MARK:- ModelMoleculeViewProtocol - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 320 } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? HeadlineBodyCaretLinkImageModel else { return } - headlineBody.setWithModel(model.headlineBody, delegateObject, additionalData) - caretButton.setWithModel(model.caretLink, delegateObject, additionalData) + headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + caretButton.setOptional(with: model.caretLink, delegateObject, additionalData) caretButton.isHidden = model.caretLink == nil - backgroundImageView.setWithModel(model.image, delegateObject, additionalData) + backgroundImageView.set(with: model.image, delegateObject, additionalData) backgroundImageView.alignFillHorizontal() backgroundImageView.alignFillVertical() } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift index b94adef0..ba2aa009 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift @@ -124,19 +124,19 @@ open class HeadlineBody: View { // MARK: - ModelMoleculeViewProtocol //-------------------------------------------------- - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 58 } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let headlineBodyModel = model as? HeadlineBodyModel else { return } style(with: headlineBodyModel.style) - headlineLabel.setWithModel(headlineBodyModel.headline, delegateObject, additionalData) - messageLabel.setWithModel(headlineBodyModel.body, delegateObject, additionalData) + headlineLabel.setOptional(with: headlineBodyModel.headline, delegateObject, additionalData) + messageLabel.setOptional(with: headlineBodyModel.body, delegateObject, additionalData) } //-------------------------------------------------- diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift index a0f22f34..90183e6e 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift @@ -108,15 +108,15 @@ import UIKit } // MARK:- ModelMoleculeViewProtocol - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 320 } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? HeadlineBodyButtonModel else { return } buttonHeadlinePadding = model.buttonHeadlinePadding - headlineBody.setWithModel(model.headlineBody, delegateObject, additionalData) - button.setWithModel(model.button, delegateObject, additionalData) + headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + button.set(with: model.button, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLink.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLink.swift index 6009c7e0..e9bfabaa 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLink.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLink.swift @@ -67,14 +67,14 @@ import UIKit } // MARK:- ModelMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? HeadlineBodyLinkModel else { return } - headlineBody.setWithModel(model.headlineBody, delegateObject, additionalData) - link.setWithModel(model.link, delegateObject, additionalData) + headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + link.set(with: model.link, delegateObject, additionalData) } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 60 } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift index ac6613ea..48f39fa0 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift @@ -10,7 +10,7 @@ import UIKit // This class is only temporarily necessary. Eventually we will have initWithModel instad of just init for moleculeviews, which will remove this need. open class StringAndMoleculeStack: MoleculeStackView { - override func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let model = stackModel else { return } for stackItemModel in model.molecules { guard let stringAndMoleculeModel = stackItemModel.molecule as? StringAndMoleculeModel, @@ -21,7 +21,7 @@ open class StringAndMoleculeStack: MoleculeStackView { } let view = StringAndMoleculeView(string: stringAndMoleculeModel.string, molecule: molecule) let stackItem = MoleculeStackItem(andContain: view) - stackItem.setWithModel(stackItemModel, delegateObject, nil) + stackItem.set(with: stackItemModel, delegateObject, nil) stackItems.append(stackItem) } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift index ffd23b0a..95392b8d 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift @@ -76,11 +76,11 @@ open class StringAndMoleculeView: View { (molecule as? MoleculeViewProtocol)?.reset?() } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? StringAndMoleculeModel else { return } label.text = model.string - molecule.setWithModel(model.molecule, delegateObject, additionalData) + molecule.set(with: model.molecule, delegateObject, additionalData) } func updateLeftViewWidthConstraint(_ percent: CGFloat) { diff --git a/MVMCoreUI/Organisms/Carousel.swift b/MVMCoreUI/Organisms/Carousel.swift index 7262e122..9e2422e6 100644 --- a/MVMCoreUI/Organisms/Carousel.swift +++ b/MVMCoreUI/Organisms/Carousel.swift @@ -83,8 +83,8 @@ open class Carousel: View { } // MARK: - MVMCoreUIMoleculeViewProtocol - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let carouselModel = model as? CarouselModel else { return } collectionView.backgroundColor = backgroundColor collectionView.layer.borderColor = backgroundColor?.cgColor @@ -159,7 +159,7 @@ open class Carousel: View { /// 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 = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) , - let moleculeName = (className as? ModelMoleculeViewProtocol.Type)?.nameForReuse(molecule, delegateObject) ?? molecule.moleculeName else { + let moleculeName = (className as? ModelMoleculeViewProtocol.Type)?.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName else { return nil } return (moleculeName, className, molecule) @@ -275,7 +275,7 @@ extension Carousel: UICollectionViewDataSource { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: moleculeInfo.identifier, for: indexPath) if let protocolCell = cell as? MVMCoreUIMoleculeViewProtocol & ModelMoleculeViewProtocol { protocolCell.reset?() - protocolCell.setWithModel(moleculeInfo.molecule, nil, nil) + protocolCell.set(with: moleculeInfo.molecule, nil, nil) protocolCell.updateView(collectionView.bounds.width) } setAccessiblity(cell, index: indexPath.row) diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index d6f934a7..653e2ebf 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -33,7 +33,7 @@ open class MoleculeStackView: Stack { // MARK: - Adding to stack /// Creates all of the stackItems for the stackItemModels - override func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { if let stackItem = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model, delegateObject) as? MoleculeStackItem { diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index 0226412b..b0841e7c 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -9,7 +9,7 @@ import Foundation -open class Stack: Container where T: StackModelProtocol { +open class Stack: Container where T: (StackModelProtocol & MoleculeModelProtocol) { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -24,7 +24,7 @@ open class Stack: Container where T: StackModelProtocol { // MARK: - Helpers //-------------------------------------------------- - public func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) { + open func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) { let constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: relation, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant) constraint.priority = priority @@ -32,7 +32,7 @@ open class Stack: Container where T: StackModelProtocol { } /// Restacks the existing items. - func restack() { + open func restack() { removeAllItemViews() guard let stackModel = stackModel else { return } let stackItems = self.stackItems @@ -49,7 +49,7 @@ open class Stack: Container where T: StackModelProtocol { } /// Removes all stack items views from the view. - func removeAllItemViews() { + open func removeAllItemViews() { for item in stackItems { item.removeFromSuperview() } @@ -63,20 +63,52 @@ open class Stack: Container where T: StackModelProtocol { super.init(frame: frame) } - public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + /// The main initializer for model driven + public init(with model: T, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.init(frame: .zero) + setOptional(with: model, delegateObject, additionalData) + } + + /// The main initializer for hardcode driven + public init(with model: T, stackItems: [UIView]) { super.init(frame: CGRect.zero) - setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + self.model = model + self.stackItems = stackItems } public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } + /// Returns a Stack created with a StackModel and StackItems containing the passed in views. + public static func createStack(with views: [UIView], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) -> Stack { + var items: [StackItem] = [] + var models: [StackItemModel] = [] + for view in views { + items.append(StackItem(andContain: view)) + models.append(StackItemModel()) + } + let model = StackModel(molecules: models, axis: axis, spacing: spacing) + return Stack(with: model, stackItems: items) + } + + /// Returns a Stack created with a StackModel containing the passed in views and using the passed in stackitems. + public static func createStack(with viewModels:[(view: UIView, model: StackItemModel)], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) -> Stack { + var stackItems: [StackItem] = [] + var models: [StackItemModel] = [] + for item in viewModels { + stackItems.append(StackItem(andContain: item.view)) + models.append(item.model) + } + let model = StackModel(molecules: models, axis: axis, spacing: spacing) + return Stack(with: model, stackItems: stackItems) + } + //-------------------------------------------------- // MARK: - MFViewProtocol //-------------------------------------------------- - public override func setupView() { + open override func setupView() { super.setupView() guard contentView.superview == nil else { return } MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0) @@ -88,7 +120,7 @@ open class Stack: Container where T: StackModelProtocol { contentView.setContentHuggingPriority(.defaultHigh, for: .horizontal) } - public override func updateView(_ size: CGFloat) { + open override func updateView(_ size: CGFloat) { super.updateView(size) for item in stackItems { (item as? MVMCoreViewProtocol)?.updateView(size) @@ -99,7 +131,7 @@ open class Stack: Container where T: StackModelProtocol { // MARK: - MVMCoreUIMoleculeViewProtocol //-------------------------------------------------- - public override func reset() { + open override func reset() { super.reset() backgroundColor = .clear for item in stackItems { @@ -107,13 +139,13 @@ open class Stack: Container where T: StackModelProtocol { } } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { let previousModel = self.model - super.setWithModel(model, delegateObject, additionalData) + super.set(with: model, delegateObject, additionalData) removeAllItemViews() // If the items in the stack are different, clear them, create new ones. - if (previousModel == nil) || Self.nameForReuse(previousModel, delegateObject) != Self.nameForReuse(model, delegateObject) { + if (previousModel == nil) || Self.nameForReuse(with: previousModel!, delegateObject) != Self.nameForReuse(with: model, delegateObject) { stackItems = [] createStackItemsFromModel(model, delegateObject, additionalData) } else { @@ -123,7 +155,7 @@ open class Stack: Container where T: StackModelProtocol { restack() } - public override class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + open override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { // This will aggregate names of molecules to make an id. guard let model = model as? T else { return "stack<>" @@ -132,7 +164,7 @@ open class Stack: Container where T: StackModelProtocol { for case let item in model.molecules { if let moleculeName = item.moleculeName { if let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? ModelMoleculeViewProtocol.Type, - let nameForReuse = moleculeClass.nameForReuse(item, delegateObject) { + let nameForReuse = moleculeClass.nameForReuse(with: item, delegateObject) { name.append(nameForReuse + ",") } else { name.append(moleculeName + ",") @@ -144,14 +176,14 @@ open class Stack: Container where T: StackModelProtocol { } // Need to update to take into account first spacing flag - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - guard let model = molecule as? T else { return 0 } + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let model = model as? T else { return 0 } let horizontal = model.axis == .horizontal var estimatedHeight: CGFloat = 0 for case let item in model.molecules { if item.gone { continue } - let height = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: item, delegateObject: delegateObject) ?? 0 + let height = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(with: item, delegateObject) ?? 0 if !horizontal { // Vertical stack aggregates the items let spacing = item.spacing ?? model.spacing @@ -164,11 +196,11 @@ open class Stack: Container where T: StackModelProtocol { return estimatedHeight } - public override class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let model = molecule as? T else { return nil } + open override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let model = model as? T else { return nil } var modules: [String] = [] for case let item in model.molecules { - if let modulesForMolecule = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.requiredModules(item, delegateObject: delegateObject, error: error) { + if let modulesForMolecule = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.requiredModules(with: item, delegateObject, error: error) { modules += modulesForMolecule } } @@ -180,19 +212,43 @@ open class Stack: Container where T: StackModelProtocol { //-------------------------------------------------- /// Can be subclassed to create views when we get stack item models and have no views yet - func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { } + open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { } /// Can be subclassed to set stack items with model when we already have views - func setStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let models = stackModel?.molecules else { return } for (index, element) in models.enumerated() { - (stackItems[index] as? ModelMoleculeViewProtocol)?.setWithModel(element, delegateObject, additionalData) + (stackItems[index] as? ModelMoleculeViewProtocol)?.set(with: element, delegateObject, additionalData) } } //-------------------------------------------------- // MARK: - Adding to stack //-------------------------------------------------- + /// Sets the stack with StackItems containing the passed in views and creates a StackModel with StackItems. + open func setAndCreateModel(with views: [UIView]) { + var stackItems: [StackItem] = [] + var models: [StackItemModel] = [] + for view in views { + stackItems.append(StackItem(andContain: view)) + models.append(StackItemModel()) + } + self.stackItems = stackItems + model = StackModel(molecules: models) + } + + /// Sets the stack with StackItems containing the passed in views and sets the StackModel with models. + open func set(with viewModels:[(view: UIView, model: T.AnyStackItemModel)]) { + guard var stackModel = self.stackModel else { return } + var stackItems: [StackItem] = [] + var models: [T.AnyStackItemModel] = [] + for item in viewModels { + stackItems.append(StackItem(andContain: item.view)) + models.append(item.model) + } + stackModel.molecules = models + self.stackItems = stackItems + } /// Gets the percent modifier. This value is used to help properly calculate percent for stack items when spacing is involved. private func getTotalSpace() -> CGFloat { diff --git a/MVMCoreUI/Organisms/StackModel.swift b/MVMCoreUI/Organisms/StackModel.swift index 93712612..46f68c3b 100644 --- a/MVMCoreUI/Organisms/StackModel.swift +++ b/MVMCoreUI/Organisms/StackModel.swift @@ -9,16 +9,20 @@ import Foundation @objcMembers public class StackModel: StackModelProtocol, MoleculeModelProtocol { + static let defaultSpacing: CGFloat = 16.0 + public static var identifier: String = "simpleStack" public var backgroundColor: Color? public var molecules: [StackItemModel] public var axis: NSLayoutConstraint.Axis = .vertical - public var spacing: CGFloat = 16.0 + public var spacing: CGFloat = StackModel.defaultSpacing public var useStackSpacingBeforeFirstItem = false - - public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis = .vertical, spacing: CGFloat? = nil) { + + public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) { self.molecules = molecules - self.axis = axis + if let axis = axis { + self.axis = axis + } if let spacing = spacing { self.spacing = spacing } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject+ModelExtension.swift b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject+ModelExtension.swift index 6249e61e..8eb0c34d 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject+ModelExtension.swift +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject+ModelExtension.swift @@ -10,7 +10,7 @@ import Foundation public extension MVMCoreUIMoleculeMappingObject { - func register(viewClass: V.Type, viewModelClass: M.Type) { + func register(viewClass: V.Type, viewModelClass: M.Type) { try? ModelRegistry.register(viewModelClass) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(viewClass, forKey: viewModelClass.identifier as NSString) } @@ -34,7 +34,7 @@ public extension MVMCoreUIMoleculeMappingObject { let setData = {() in if let molecule = molecule as? ModelMoleculeViewProtocol { - molecule.setWithModel(model, delegateObject, nil) + molecule.set(with: model, delegateObject, nil) } else { molecule.setWithJSON?(model.toJSON(), delegateObject: delegateObject, additionalData: nil) } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 9741f110..33d6beb0 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -106,7 +106,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { guard let moleculeInfo = moleculesInfo?[indexPath.row], - let estimatedHeight = (moleculeInfo.class as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: moleculeInfo.molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) + let estimatedHeight = (moleculeInfo.class as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject) else { return 0 } return estimatedHeight @@ -130,7 +130,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol protocolCell.setLines(with: templateModel?.line, delegateObject: delegate, additionalData: nil, indexPath: indexPath) } - (moleculeCell as? ModelMoleculeViewProtocol)?.setWithModel(moleculeInfo.molecule, delegate, nil) + (moleculeCell as? ModelMoleculeViewProtocol)?.set(with: moleculeInfo.molecule, delegate, nil) moleculeCell?.updateView(tableView.bounds.width) return cell @@ -283,7 +283,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol guard let listItem = listItem, let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(listItem), - let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol.Type)?.nameForReuse(listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName + let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol.Type)?.nameForReuse(with: listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName else { return nil } return (moleculeName, moleculeClass, listItem) diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index ef7a470d..e05a067a 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -55,7 +55,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { let stack = MoleculeStackView(frame: .zero) moleculeStackModel.useStackSpacingBeforeFirstItem = true moleculeStackModel.useHorizontalMargins = true - stack.setWithModel(moleculeStackModel, delegateObject() as? MVMCoreUIDelegateObject, nil) + stack.set(with: moleculeStackModel, delegateObject() as? MVMCoreUIDelegateObject, nil) return stack } From 6a2858576521d709cb8b95b2ba376090fbe5d54a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 27 Feb 2020 13:58:44 -0500 Subject: [PATCH 34/48] merge fix --- MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift index d6374d78..3cd601b6 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift @@ -20,8 +20,8 @@ open class ExternalLink: Link { // MARK: - ModelMoleculeViewProtocol //-------------------------------------------------- - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? ExternalLinkModel else { return } From 19ce1087eba605e327d26ae69d6268d9d773d197 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Fri, 28 Feb 2020 19:44:23 +0530 Subject: [PATCH 35/48] Removing percentage. --- .../ListLeftVariableRadioButtonAndPaymentMethod.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift index 7667340c..f5865423 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift @@ -39,9 +39,9 @@ import UIKit eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) // Create a stack model to use for the internal stack and set the alignment of labels - let stackModel = StackModel(molecules: [StackItemModel(percent:10,horizontalAlignment: .center), - StackItemModel(percent:10,horizontalAlignment: .fill), - StackItemModel(percent:80,horizontalAlignment: .leading)], + let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill), + StackItemModel(horizontalAlignment: .fill), + StackItemModel(horizontalAlignment: .leading)], axis: .horizontal) stack.model = stackModel stack.restack() From 36e34e1726316ce2e70bd696bcab34b458082bc5 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 28 Feb 2020 10:30:57 -0500 Subject: [PATCH 36/48] fixes --- MVMCoreUI/Atoms/Views/Label/Label.swift | 4 +- MVMCoreUI/Atoms/Views/Label/LabelModel.swift | 4 +- MVMCoreUI/Atoms/Views/RadioButton.swift | 4 +- ...tVariableRadioButtonAndPaymentMethod.swift | 62 ++++++++++++------- ...ableRadioButtonAndPaymentMethodModel.swift | 12 +++- 5 files changed, 54 insertions(+), 32 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index 0b1e896c..c7e72204 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -354,8 +354,8 @@ public typealias ActionBlock = () -> () } } - if let textColorHex = labelModel.textColor, !textColorHex.isEmpty { - textColor = UIColor.mfGet(forHex: textColorHex) + if let color = labelModel.textColor { + textColor = color.uiColor } if let attributes = labelModel.attributes, let labelText = text { diff --git a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift index cb9cc0a9..3b5f2b66 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift @@ -18,7 +18,7 @@ import Foundation public var backgroundColor: Color? public var text: String public var accessibilityText: String? - public var textColor: String? + public var textColor: Color? public var fontStyle: String? public var fontName: String? public var fontSize: CGFloat? @@ -68,7 +68,7 @@ import Foundation let typeContainer = try decoder.container(keyedBy: CodingKeys.self) text = try typeContainer.decode(String.self, forKey: .text) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) - textColor = try typeContainer.decodeIfPresent(String.self, forKey: .textColor) + textColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) fontStyle = try typeContainer.decodeIfPresent(String.self, forKey: .fontStyle) fontName = try typeContainer.decodeIfPresent(String.self, forKey: .fontName) diff --git a/MVMCoreUI/Atoms/Views/RadioButton.swift b/MVMCoreUI/Atoms/Views/RadioButton.swift index ac579b23..47eeb0ca 100644 --- a/MVMCoreUI/Atoms/Views/RadioButton.swift +++ b/MVMCoreUI/Atoms/Views/RadioButton.swift @@ -99,8 +99,8 @@ import UIKit accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? RadioButtonModel else { return } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift index f5865423..b4bb2fc3 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift @@ -12,42 +12,56 @@ import UIKit //----------------------------------------------------- // MARK: - Outlets - //------------------------------------------------------- + //----------------------------------------------------- let radioButton = RadioButton(frame: .zero) let leftImage = MFLoadImageView(pinnedEdges: .all) let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink() - let stack = Stack(frame: .zero) + var stack: Stack + + //----------------------------------------------------- + // MARK: - Initializers + //----------------------------------------------------- + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: radioButton, model: StackItemModel(horizontalAlignment: .fill)), + (view: leftImage, model: StackItemModel(horizontalAlignment: .fill)), + (view: eyebrowHeadlineBodyLink, model: StackItemModel(horizontalAlignment: .leading))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } //----------------------------------------------------- // MARK: - View Lifecycle - //------------------------------------------------------- + //----------------------------------------------------- override open func setupView() { super.setupView() - stack.stackItems = [StackItem(andContain: radioButton), - StackItem(andContain: leftImage), - StackItem(andContain: eyebrowHeadlineBodyLink)] addMolecule(stack) - } - //---------------------------------------------------- - // MARK: - Molecule - //----------------------------------------------------- - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) - guard let model = model as? ListLeftVariableRadioButtonAndPaymentMethodModel else { return} - radioButton.setWithModel(model.radioButton, delegateObject, additionalData) - leftImage.setWithModel(model.image, delegateObject, additionalData) - eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) - - // Create a stack model to use for the internal stack and set the alignment of labels - let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill), - StackItemModel(horizontalAlignment: .fill), - StackItemModel(horizontalAlignment: .leading)], - axis: .horizontal) - stack.model = stackModel stack.restack() + eyebrowHeadlineBodyLink.body.textColor = .mvmOrangeAA + eyebrowHeadlineBodyLink.headline.styleBoldBodySmall(true) } - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override func reset() { + super.reset() + eyebrowHeadlineBodyLink.body.textColor = .mvmOrangeAA + eyebrowHeadlineBodyLink.headline.styleBoldBodySmall(true) + } + + //---------------------------------------------------- + // MARK: - Molecule + //---------------------------------------------------- + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListLeftVariableRadioButtonAndPaymentMethodModel else { return} + radioButton.set(with: model.radioButton, delegateObject, additionalData) + leftImage.set(with: model.image, delegateObject, additionalData) + eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 90 } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift index e7b41635..5ea28778 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift @@ -10,9 +10,9 @@ import Foundation public class ListLeftVariableRadioButtonAndPaymentMethodModel: ListItemModel, MoleculeModelProtocol { public static var identifier: String = "listLVRBImg" - public var radioButton : RadioButtonModel + public var radioButton: RadioButtonModel public var image: ImageViewModel - public var eyebrowHeadlineBodyLink : EyebrowHeadlineBodyLinkModel + public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel public init(radioButton: RadioButtonModel, image: ImageViewModel, eyebrowHeadlineBodyLink:EyebrowHeadlineBodyLinkModel) { self.radioButton = radioButton @@ -21,6 +21,14 @@ public class ListLeftVariableRadioButtonAndPaymentMethodModel: ListItemModel, Mo super.init() } + public override func setDefaults() { + super.setDefaults() + if image.width == nil, image.height == nil { + image.width = 32 + image.height = 32 + } + } + private enum CodingKeys: String, CodingKey { case moleculeName case radioButton From f779478cc58e5b3f7d8b61f87ba78c071d615a5d Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 28 Feb 2020 10:32:27 -0500 Subject: [PATCH 37/48] update --- MVMCoreUI.xcodeproj/project.pbxproj | 2 +- MVMCoreUI/Atoms/Views/RadioButtonModel.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index c4c93c6e..1b2654c3 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -1341,8 +1341,8 @@ 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */, 0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */, - 01004F2F22721C3800991ECC /* RadioButton.swift */, 011D95AE2407266E000E3791 /* RadioButtonModel.swift */, + 01004F2F22721C3800991ECC /* RadioButton.swift */, D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */, 943784F3236B77BB006A1E82 /* GraphView.swift */, 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */, diff --git a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift index b061e35e..c8443691 100644 --- a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift +++ b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift @@ -12,6 +12,6 @@ import Foundation public class RadioButtonModel: MoleculeModelProtocol { public static var identifier: String = "radioButton" public var backgroundColor: Color? - public var state: Bool? + public var state: Bool = false public var fieldKey: String? } From f230291e4787eb583f1fa5e8a0435e2b71943690 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 28 Feb 2020 11:36:14 -0500 Subject: [PATCH 38/48] color --- MVMCoreUI/CustomPrimitives/Color.swift | 46 +++++++++++++++++--------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/MVMCoreUI/CustomPrimitives/Color.swift b/MVMCoreUI/CustomPrimitives/Color.swift index 165fa8ad..f06b337c 100644 --- a/MVMCoreUI/CustomPrimitives/Color.swift +++ b/MVMCoreUI/CustomPrimitives/Color.swift @@ -62,6 +62,14 @@ public final class Color: Codable { determineRGBA() } + public init?(colorString: String) throws { + let components = try Color.getColorComponents(for: colorString) + self.uiColor = components.color + hex = components.hex + name = components.name ?? "" + determineRGBA() + } + //-------------------------------------------------- // MARK: - Codable Initializers //-------------------------------------------------- @@ -69,21 +77,10 @@ public final class Color: Codable { required public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let colorString = try container.decode(String.self) - - if colorString.hasPrefix("#") { - hex = colorString.replacingOccurrences(of: "#", with: "") - } else { - guard let hex = UIColor.names[colorString]?.hex else { throw ColorError.badName(reason: "Check the spelling of your color.") } - self.hex = hex.replacingOccurrences(of: "#", with: "") - name = colorString - } - - if hex.count == 8 { - uiColor = UIColor.getColorWithTransparencyBy(hex: hex) - } else { - uiColor = UIColor.getColorBy(hex: hex) - } - + let components = try Color.getColorComponents(for: colorString) + self.uiColor = components.color + hex = components.hex + name = components.name ?? "" determineRGBA() } @@ -95,6 +92,25 @@ public final class Color: Codable { //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- + private static func getColorComponents(for colorString: String) throws -> (color: UIColor, hex: String, name: String?) { + var color: UIColor + var hex: String + var name: String? + if colorString.hasPrefix("#") { + hex = colorString.replacingOccurrences(of: "#", with: "") + } else { + guard let hexString = UIColor.names[colorString]?.hex else { throw ColorError.badName(reason: "Check the spelling of your color.") } + hex = hexString.replacingOccurrences(of: "#", with: "") + name = colorString + } + + if hex.count == 8 { + color = UIColor.getColorWithTransparencyBy(hex: hex) + } else { + color = UIColor.getColorBy(hex: hex) + } + return (color, hex, name) + } public func convertHexToFloat(start: String.Index, end: String.Index) -> CGFloat { From 527cdc684d7caaa5f74b3092c70062202ec3eb56 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 28 Feb 2020 12:17:44 -0500 Subject: [PATCH 39/48] Small updates --- .../ListFourColumnDataUsageDivider.swift | 59 ++++++++++--------- .../ListFourColumnDataUsageDividerModel.swift | 3 +- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift index cd103787..35968599 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift @@ -11,50 +11,53 @@ import Foundation @objcMembers open class ListFourColumnDataUsageDivider: TableViewCell { // MARK: - MFViewProtocol - let label1 = Label.commonLabelB1(true) - let label2 = Label.commonLabelB1(true) - let label3 = Label.commonLabelB1(true) - let label4 = Label.commonLabelB1(true) - let stack = Stack(frame: .zero) + let label1 = Label.createLabelBoldBodySmall(true) + let label2 = Label.createLabelBoldBodySmall(true) + let label3 = Label.createLabelBoldBodySmall(true) + let label4 = Label.createLabelBoldBodySmall(true) + var stack: Stack + + // MARK: - Initializers + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: label1, model: StackItemModel(percent: 19, horizontalAlignment: .leading)), + (view: label2, model: StackItemModel(percent: 44, horizontalAlignment: .leading)), + (view: label3, model: StackItemModel(percent: 17, horizontalAlignment: .leading)), + (view: label4, model: StackItemModel(percent: 20, horizontalAlignment: .leading))], + axis: .horizontal, spacing: 8) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } // MARK: - MFViewProtocol open override func setupView() { super.setupView() - stack.stackItems = [StackItem(andContain: label1), - StackItem(andContain: label2), - StackItem(andContain: label3), - StackItem(andContain: label4)] addMolecule(stack) + stack.restack() } // MARK: - MVMCoreUIMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.setWithModel(model, delegateObject, additionalData) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) guard let model = model as? ListFourColumnDataUsageDividerModel else { return } - label1.setWithModel(model.label1, delegateObject, additionalData) - label2.setWithModel(model.label2, delegateObject, additionalData) - label3.setWithModel(model.label3, delegateObject, additionalData) - label4.setWithModel(model.label4, delegateObject, additionalData) - //Create a stack model to use for the internal stack and set the alignment of labels - let stackModel = StackModel(molecules: [StackItemModel(percent: 15, horizontalAlignment: .leading), - StackItemModel(percent: 35, horizontalAlignment: .leading), - StackItemModel(percent: 30, horizontalAlignment: .trailing), - StackItemModel(percent: 20, horizontalAlignment: .trailing)], - axis: .horizontal) - stack.model = stackModel - stack.restack() + label1.set(with: model.label1, delegateObject, additionalData) + label2.set(with: model.label2, delegateObject, additionalData) + label3.set(with: model.label3, delegateObject, additionalData) + label4.set(with: model.label4, delegateObject, additionalData) } // MARK: - MVMCoreUIMoleculeViewProtocol open override func reset() { super.reset() - label1.styleB1(true) - label2.styleB1(true) - label3.styleB1(true) - label4.styleB1(true) + label1.styleBoldBodySmall(true) + label2.styleBoldBodySmall(true) + label3.styleBoldBodySmall(true) + label4.styleBoldBodySmall(true) } - open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { return 121 } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift index 1277f4bb..f9ce88d8 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDividerModel.swift @@ -21,10 +21,9 @@ public class ListFourColumnDataUsageDividerModel: ListItemModel, MoleculeModelPr self.label3 = label3 self.label4 = label4 super.init() - setDefaults() } - // Defaults to set + /// Defaults to set override public func setDefaults() { super.setDefaults() style = "tallDivider" From 27e1a97a80fa371a4a5ecbe0ad3c0151f441c76e Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 28 Feb 2020 12:21:13 -0500 Subject: [PATCH 40/48] order update --- .../OtherHandlers/MoleculeObjectMapping.swift | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 3d86b35a..34da2080 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -57,20 +57,13 @@ import Foundation // Horizontal Combination Molecules MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) - - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) - // Vertical Combination Molecules MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadLineBodyCaretLinkImage.self, viewModelClass: HeadlineBodyCaretLinkImageModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: EyebrowHeadlineBodyLink.self, viewModelClass: EyebrowHeadlineBodyLinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLink.self, viewModelClass: HeadlineBodyLinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyButton.self, viewModelClass: HeadlineBodyButtonModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self) // Left Right Molecules MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CornerLabels.self, viewModelClass: CornerLabelsModel.self) @@ -79,10 +72,6 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyToggle.self, viewModelClass: HeadlineBodyToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableIconWithRightCaret.self, viewModelClass: ListLeftVariableIconWithRightCaretModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self) // List items MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: MoleculeListItemModel.self) @@ -107,6 +96,18 @@ import Foundation // Other Organisms MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Carousel.self, viewModelClass: CarouselModel.self) + // Designed List Items + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableIconWithRightCaret.self, viewModelClass: ListLeftVariableIconWithRightCaretModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) + + // Designed Section Dividers + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self) + // TODO: Need model MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(DigitEntryField.self, forKey: "digitTextField" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(DateDropdownEntryField.self, forKey: "dateDropdownEntryField" as NSString) From cfd6cb13580436b8f6b6ef49895e8fef3b38c6a1 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 28 Feb 2020 13:06:11 -0500 Subject: [PATCH 41/48] Teting --- MVMCoreUI.xcodeproj/project.pbxproj | 5 ++- ...ariableCheckboxAllTextAndLinksCustom.swift | 43 +++++++++++++++++++ ...VariableCheckboxAllTextAndLinksModel.swift | 4 +- .../OtherHandlers/MoleculeObjectMapping.swift | 3 ++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksCustom.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index b6167eb1..bc4c2af5 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -215,6 +215,7 @@ D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */; }; D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */; }; D28A839323CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A839223CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift */; }; + D28D6F71240988720046BD9D /* ListLeftVariableCheckboxAllTextAndLinksCustom.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28D6F70240988720046BD9D /* ListLeftVariableCheckboxAllTextAndLinksCustom.swift */; }; D296E14722A5984C0051EBE7 /* MVMCoreUIViewConstrainingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */; }; D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -559,6 +560,7 @@ D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonViewModel.swift; sourceTree = ""; }; D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerLabelsModel.swift; sourceTree = ""; }; D28A839223CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyCaretLinkImageModel.swift; sourceTree = ""; }; + D28D6F70240988720046BD9D /* ListLeftVariableCheckboxAllTextAndLinksCustom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksCustom.swift; sourceTree = ""; }; D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewConstrainingProtocol.h; sourceTree = ""; }; D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsView.m; sourceTree = ""; }; D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLabelsView.h; sourceTree = ""; }; @@ -1064,6 +1066,7 @@ 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */, 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, + D28D6F70240988720046BD9D /* ListLeftVariableCheckboxAllTextAndLinksCustom.swift */, ); path = LeftVariable; sourceTree = ""; @@ -1072,7 +1075,6 @@ isa = PBXGroup; children = ( 525019E3240684E500EED91C /* FourColumn */, - 52267A0523FFE0A900906CBA /* OneColumn */, D22B38ED23F4E11100490EF6 /* ThreeColumn */, ); path = SectionDividers; @@ -1727,6 +1729,7 @@ D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */, 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, + D28D6F71240988720046BD9D /* ListLeftVariableCheckboxAllTextAndLinksCustom.swift in Sources */, D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */, 017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksCustom.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksCustom.swift new file mode 100644 index 00000000..64394c1c --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksCustom.swift @@ -0,0 +1,43 @@ +// +// ListLeftVariableCheckboxAllTextAndLinksCustom.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 2/28/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListLeftVariableCheckboxAllTextAndLinksModelCustom: ListLeftVariableCheckboxAllTextAndLinksModel { + public override class var identifier: String { + return "listLVCBCustom" + } + + required public init(from decoder: Decoder) throws { + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + } +} + +@objcMembers open class ListLeftVariableCheckboxAllTextAndLinksCustom: ListLeftVariableCheckboxAllTextAndLinks { + // MARK:- MVMCoreUIMoleculeViewProtocol + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + + // Update immediately. + eyebrowHeadlineBodyLink.stack.stackModel?.molecules[0].gone = !checkbox.isSelected + eyebrowHeadlineBodyLink.stack.restack() + + // Update on press. + checkbox.actionBlock = { [weak self] in + guard let self = self else { return } + print("hello") + self.eyebrowHeadlineBodyLink.stack.stackModel?.molecules[0].gone = !self.checkbox.isSelected + self.eyebrowHeadlineBodyLink.stack.restack() + delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) + } + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift index fec71c0b..4217b72a 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift @@ -9,7 +9,9 @@ import Foundation public class ListLeftVariableCheckboxAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { - public static var identifier: String = "listLVCB" + public class var identifier: String { + return "listLVCB" + } public var checkbox: CheckboxModel public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 34da2080..68475878 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -103,6 +103,9 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) + + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinksCustom.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModelCustom.self) + // Designed Section Dividers MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) From 2d84b89af9552ef2aefaebbeadbb82a3efb2e455 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 28 Feb 2020 13:38:27 -0500 Subject: [PATCH 42/48] addressing issue where cell resizes but accessory does not follow. --- MVMCoreUI/BaseClasses/TableViewCell.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index b546ad2c..3154bbb9 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -96,8 +96,8 @@ import UIKit super.layoutSubviews() // Ensures accessory view aligns to the center y derived from the - if let center = heroAccessoryCenter { - accessoryView?.center.y = center.y + if let _ = heroAccessoryCenter { + alignAccessoryToHero() } } From 7345dce4b91f6557e2b6063c3c21d6fbf3658c7e Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 28 Feb 2020 13:46:33 -0500 Subject: [PATCH 43/48] Dropdown filter fix --- MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index dd530605..f9b9d976 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -12,8 +12,6 @@ import UIKit //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - - var dropDownListItemModel: DropDownListItemModel? let dropDown = ItemDropdownEntryField() var delegateObject: MVMCoreUIDelegateObject? var previousIndex = NSNotFound @@ -31,7 +29,7 @@ import UIKit guard newValue != oldValue, let self = self, let index = self.dropDown.pickerData.firstIndex(of: newValue), - let dropListItemJSON = self.dropDownListItemModel.toJSON(), + let dropListItemJSON = (self.listItemModel as? DropDownListItemModel).toJSON(), let json2d = dropListItemJSON.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]] else { return } From 201fa2be81860038c36c4818292aadfd52d8243d Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 28 Feb 2020 13:48:23 -0500 Subject: [PATCH 44/48] remove file testing --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ---- MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift | 3 --- 2 files changed, 7 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index bc4c2af5..339735f3 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -215,7 +215,6 @@ D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */; }; D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */; }; D28A839323CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A839223CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift */; }; - D28D6F71240988720046BD9D /* ListLeftVariableCheckboxAllTextAndLinksCustom.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28D6F70240988720046BD9D /* ListLeftVariableCheckboxAllTextAndLinksCustom.swift */; }; D296E14722A5984C0051EBE7 /* MVMCoreUIViewConstrainingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */; }; D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -560,7 +559,6 @@ D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonViewModel.swift; sourceTree = ""; }; D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerLabelsModel.swift; sourceTree = ""; }; D28A839223CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyCaretLinkImageModel.swift; sourceTree = ""; }; - D28D6F70240988720046BD9D /* ListLeftVariableCheckboxAllTextAndLinksCustom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksCustom.swift; sourceTree = ""; }; D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewConstrainingProtocol.h; sourceTree = ""; }; D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsView.m; sourceTree = ""; }; D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLabelsView.h; sourceTree = ""; }; @@ -1066,7 +1064,6 @@ 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */, 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, - D28D6F70240988720046BD9D /* ListLeftVariableCheckboxAllTextAndLinksCustom.swift */, ); path = LeftVariable; sourceTree = ""; @@ -1729,7 +1726,6 @@ D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */, 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, - D28D6F71240988720046BD9D /* ListLeftVariableCheckboxAllTextAndLinksCustom.swift in Sources */, D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */, 017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 68475878..34da2080 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -103,9 +103,6 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) - - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinksCustom.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModelCustom.self) - // Designed Section Dividers MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) From 01a36a02457f2c3c3784e549856e7a32a703ac66 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 28 Feb 2020 13:50:06 -0500 Subject: [PATCH 45/48] remove test file --- ...ariableCheckboxAllTextAndLinksCustom.swift | 43 ------------------- 1 file changed, 43 deletions(-) delete mode 100644 MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksCustom.swift diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksCustom.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksCustom.swift deleted file mode 100644 index 64394c1c..00000000 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksCustom.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// ListLeftVariableCheckboxAllTextAndLinksCustom.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 2/28/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -public class ListLeftVariableCheckboxAllTextAndLinksModelCustom: ListLeftVariableCheckboxAllTextAndLinksModel { - public override class var identifier: String { - return "listLVCBCustom" - } - - required public init(from decoder: Decoder) throws { - try super.init(from: decoder) - } - - public override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - } -} - -@objcMembers open class ListLeftVariableCheckboxAllTextAndLinksCustom: ListLeftVariableCheckboxAllTextAndLinks { - // MARK:- MVMCoreUIMoleculeViewProtocol - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.set(with: model, delegateObject, additionalData) - - // Update immediately. - eyebrowHeadlineBodyLink.stack.stackModel?.molecules[0].gone = !checkbox.isSelected - eyebrowHeadlineBodyLink.stack.restack() - - // Update on press. - checkbox.actionBlock = { [weak self] in - guard let self = self else { return } - print("hello") - self.eyebrowHeadlineBodyLink.stack.stackModel?.molecules[0].gone = !self.checkbox.isSelected - self.eyebrowHeadlineBodyLink.stack.restack() - delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) - } - } -} From 2e99d980e8721ff45329d00622d49264ea474d44 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 28 Feb 2020 14:08:38 -0500 Subject: [PATCH 46/48] open for mobile first --- .../Containers/Views/Container/ContainerModel.swift | 4 ++-- ...istLeftVariableCheckboxAllTextAndLinksModel.swift | 4 ++-- MVMCoreUI/Molecules/Items/ListItemModel.swift | 6 +++--- .../EyebrowHeadlineBodyLink.swift | 12 ++++++------ MVMCoreUI/Organisms/MoleculeStackView.swift | 2 +- MVMCoreUI/Organisms/Stack.swift | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/MVMCoreUI/Containers/Views/Container/ContainerModel.swift b/MVMCoreUI/Containers/Views/Container/ContainerModel.swift index a5e89adb..a18e8589 100644 --- a/MVMCoreUI/Containers/Views/Container/ContainerModel.swift +++ b/MVMCoreUI/Containers/Views/Container/ContainerModel.swift @@ -8,7 +8,7 @@ import Foundation -public class ContainerModel: ContainerModelProtocol, Codable { +open class ContainerModel: ContainerModelProtocol, Codable { public var horizontalAlignment: UIStackView.Alignment? public var verticalAlignment: UIStackView.Alignment? public var useHorizontalMargins: Bool? @@ -48,7 +48,7 @@ public class ContainerModel: ContainerModelProtocol, Codable { bottomMarginPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .bottomMarginPadding) } - public func encode(to encoder: Encoder) throws { + open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: verticalAlignment), forKey: .verticalAlignment) try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: horizontalAlignment), forKey: .horizontalAlignment) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift index 4217b72a..188af025 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift @@ -8,8 +8,8 @@ import Foundation -public class ListLeftVariableCheckboxAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { - public class var identifier: String { +open class ListLeftVariableCheckboxAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { + open class var identifier: String { return "listLVCB" } public var checkbox: CheckboxModel diff --git a/MVMCoreUI/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Molecules/Items/ListItemModel.swift index 973a487a..4e0ccd35 100644 --- a/MVMCoreUI/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/ListItemModel.swift @@ -9,7 +9,7 @@ import Foundation -@objcMembers public class ListItemModel: ContainerModel, ListItemModelProtocol { +@objcMembers open class ListItemModel: ContainerModel, ListItemModelProtocol { public var backgroundColor: Color? public var action: ActionModelProtocol? public var hideArrow: Bool? @@ -25,7 +25,7 @@ import Foundation } /// Defaults to set - public func setDefaults() { + open func setDefaults() { if useHorizontalMargins == nil { useHorizontalMargins = true } @@ -53,7 +53,7 @@ import Foundation setDefaults() } - public override func encode(to encoder: Encoder) throws { + open override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index 58fa2d00..49b08b44 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -13,11 +13,11 @@ import UIKit // MARK: - Outlets //-------------------------------------------------- - let stack = Stack(frame: .zero) - let eyebrow = Label.commonLabelB3(true) - let headline = Label.commonLabelB1(true) - let body = Label.commonLabelB2(true) - let link = Link() + public let stack = Stack(frame: .zero) + public let eyebrow = Label.commonLabelB3(true) + public let headline = Label.commonLabelB1(true) + public let body = Label.commonLabelB2(true) + public let link = Link() var casteModel: EyebrowHeadlineBodyLinkModel? { get { return model as? EyebrowHeadlineBodyLinkModel } @@ -72,7 +72,7 @@ import UIKit stack.restack() } - public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 65 } } diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index 653e2ebf..12d79dcd 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -9,7 +9,7 @@ import UIKit open class MoleculeStackView: Stack { - override var stackModel: MoleculeStackModel? { + open override var stackModel: MoleculeStackModel? { get { return model as? MoleculeStackModel } } diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index b0841e7c..696964f1 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -14,11 +14,11 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto // MARK: - Properties //-------------------------------------------------- - var contentView: UIView = MVMCoreUICommonViewsUtility.commonView() - var stackModel: T? { + open var contentView: UIView = MVMCoreUICommonViewsUtility.commonView() + open var stackModel: T? { get { return model as? T } } - var stackItems: [UIView] = [] + open var stackItems: [UIView] = [] //-------------------------------------------------- // MARK: - Helpers From 6b93270431957c4a48aaa34438e5dbf9a45c1b3b Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 2 Mar 2020 10:59:24 -0500 Subject: [PATCH 47/48] opening access to prevent error --- ...VariableCheckboxAllTextAndLinksModel.swift | 22 ++++++++++++--- MVMCoreUI/Molecules/Items/ListItemModel.swift | 27 ++++++++++++++++--- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift index 188af025..d3d3aab4 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift @@ -9,32 +9,48 @@ import Foundation open class ListLeftVariableCheckboxAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + open class var identifier: String { return "listLVCB" } public var checkbox: CheckboxModel public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(checkbox: CheckboxModel, eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel) { self.checkbox = checkbox self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink super.init() } + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { case moleculeName case eyebrowHeadlineBodyLink case checkbox } - + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) checkbox = try typeContainer.decodeIfPresent(CheckboxModel.self, forKey: .checkbox) ?? CheckboxModel() try super.init(from: decoder) } - - public override func encode(to encoder: Encoder) throws { + + open override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) diff --git a/MVMCoreUI/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Molecules/Items/ListItemModel.swift index 4e0ccd35..3ff483eb 100644 --- a/MVMCoreUI/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/ListItemModel.swift @@ -10,12 +10,20 @@ import Foundation @objcMembers open class ListItemModel: ContainerModel, ListItemModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public var backgroundColor: Color? public var action: ActionModelProtocol? public var hideArrow: Bool? public var line: LineModel? public var style: String? - + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { case backgroundColor case action @@ -24,6 +32,10 @@ import Foundation case style } + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + /// Defaults to set open func setDefaults() { if useHorizontalMargins == nil { @@ -37,11 +49,19 @@ import Foundation } } + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public override init() { super.init() setDefaults() } - + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) @@ -52,7 +72,7 @@ import Foundation try super.init(from: decoder) setDefaults() } - + open override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) @@ -63,4 +83,3 @@ import Foundation try container.encodeIfPresent(style, forKey: .style) } } - From d04e87edafc71cba73f3b53ebee7b63e51e30b10 Mon Sep 17 00:00:00 2001 From: "Robinson, Blake" Date: Tue, 3 Mar 2020 15:37:58 -0500 Subject: [PATCH 48/48] Helps resolve CXTDT-63501 Gesture recognizer on Page Control needs to be public so that subclass, MFTextPageControl, can add it and remove it as needed --- MVMCoreUI/Legacy/Views/MVMCoreUIPageControl.h | 1 + MVMCoreUI/Legacy/Views/MVMCoreUIPageControl.m | 1 + 2 files changed, 2 insertions(+) diff --git a/MVMCoreUI/Legacy/Views/MVMCoreUIPageControl.h b/MVMCoreUI/Legacy/Views/MVMCoreUIPageControl.h index af699ddc..e86d3f9e 100644 --- a/MVMCoreUI/Legacy/Views/MVMCoreUIPageControl.h +++ b/MVMCoreUI/Legacy/Views/MVMCoreUIPageControl.h @@ -23,6 +23,7 @@ @property (nullable, weak, nonatomic) UIView *containerView; @property (nullable, weak, nonatomic) UIView *indicatorRectangle; @property (nullable, copy, nonatomic) PagingTouchBlock pagingTouchBlock; +@property (nullable, strong, nonatomic) UITapGestureRecognizer *tapGestureRecognizer; ///set YES to make the accessibility value as "Slide #currentPage of #totalPage", otherwise will be "Page #currentPage of #totalPage", default is NO @property (nonatomic) BOOL isSlidesAcc; diff --git a/MVMCoreUI/Legacy/Views/MVMCoreUIPageControl.m b/MVMCoreUI/Legacy/Views/MVMCoreUIPageControl.m index 6648b513..9a8f880f 100644 --- a/MVMCoreUI/Legacy/Views/MVMCoreUIPageControl.m +++ b/MVMCoreUI/Legacy/Views/MVMCoreUIPageControl.m @@ -267,6 +267,7 @@ static CGFloat const IndicatorRectangleHeight = 4; UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] init]; [tapGesture addTarget:self action:@selector(rectangleTapped:)]; [self addGestureRecognizer:tapGesture]; + self.tapGestureRecognizer = tapGesture; } }