diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 1b43f48b..95bd45b6 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -96,10 +96,14 @@ 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.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 */; }; + 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; }; + 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 */; }; 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 */; }; 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; }; 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; @@ -128,8 +132,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 */; }; + AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */; }; + AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.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 */; }; @@ -141,6 +145,8 @@ C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5023C77A4800A3614A /* StringAndMoleculeStack.swift */; }; C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5123C77A4900A3614A /* NumberedList.swift */; }; C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */; }; + C7F8012123E8303200396FBD /* ListRVWheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012023E8303200396FBD /* ListRVWheel.swift */; }; + C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; }; @@ -303,7 +309,7 @@ D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */; }; D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */; }; D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */; }; - D2A514672213885800345BFB /* HeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* HeaderView.swift */; }; + D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* MoleculeHeaderView.swift */; }; D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; }; D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A638FC22CA98280052ED1F /* HeadlineBody.swift */; }; D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390022CBB1820052ED1F /* Carousel.swift */; }; @@ -318,6 +324,8 @@ D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C521A823EDE79E00CA2634 /* ViewController.swift */; }; D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; }; D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; }; + D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */; }; + D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */; }; D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; }; D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; }; D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; }; @@ -422,10 +430,14 @@ 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.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 = ""; }; + 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = ""; }; + 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 = ""; }; 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 = ""; }; 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = ""; }; 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = ""; }; 943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = ""; }; @@ -453,8 +465,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 = ""; }; + AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePayments.swift; sourceTree = ""; }; + AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.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 = ""; }; @@ -466,6 +478,8 @@ C6FA7D5023C77A4800A3614A /* StringAndMoleculeStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeStack.swift; sourceTree = ""; }; C6FA7D5123C77A4900A3614A /* NumberedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberedList.swift; sourceTree = ""; }; C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadLineBodyCaretLinkImage.swift; sourceTree = ""; }; + C7F8012023E8303200396FBD /* ListRVWheel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRVWheel.swift; sourceTree = ""; }; + C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = ""; }; @@ -642,7 +656,7 @@ D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = ""; }; D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackTemplate.swift; sourceTree = ""; }; D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackCenteredTemplate.swift; sourceTree = ""; }; - D2A514662213885800345BFB /* HeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderView.swift; sourceTree = ""; }; + D2A514662213885800345BFB /* MoleculeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderView.swift; sourceTree = ""; }; D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerViewController.swift; sourceTree = ""; }; D2A638FC22CA98280052ED1F /* HeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBody.swift; sourceTree = ""; }; D2A6390022CBB1820052ED1F /* Carousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Carousel.swift; sourceTree = ""; }; @@ -657,6 +671,8 @@ D2C521A823EDE79E00CA2634 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = ""; }; D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = ""; }; + D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderModel.swift; sourceTree = ""; }; + D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainerProtocol.swift; sourceTree = ""; }; D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = ""; }; D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = ""; }; D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = ""; }; @@ -749,12 +765,22 @@ children = ( 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */, D29E28DE23D740FC00ACEA85 /* Container */, + D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */, 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */, D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, ); path = Views; sourceTree = ""; }; + 52267A0523FFE0A900906CBA /* OneColumn */ = { + isa = PBXGroup; + children = ( + 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */, + 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */, + ); + path = OneColumn; + sourceTree = ""; + }; 946EE1B5237B663A0036751F /* Extensions */ = { isa = PBXGroup; children = ( @@ -786,13 +812,15 @@ name = "Recovered References"; sourceTree = ""; }; - AA84562523FBB4770013B068 /* FourColumn */ = { + AA4FC2A323F4F69600E251DB /* RightVariable */ = { isa = PBXGroup; children = ( - AA84562623FBB4A80013B068 /* ListFourColumnDataUsageDivider.swift */, - AA84562823FBB4C00013B068 /* ListFourColumnDataUsageDividerModel.swift */, + AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */, + AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, + C7F8012223E846C300396FBD /* ListRVWheelModel.swift */, + C7F8012023E8303200396FBD /* ListRVWheel.swift */, ); - path = FourColumn; + path = RightVariable; sourceTree = ""; }; D213347423842FE3008E41B3 /* Controllers */ = { @@ -976,6 +1004,7 @@ D22B38EA23F4E08B00490EF6 /* List */ = { isa = PBXGroup; children = ( + AA4FC2A323F4F69600E251DB /* RightVariable */, D22B38EB23F4E0AE00490EF6 /* LeftVariable */, ); path = List; @@ -984,6 +1013,8 @@ D22B38EB23F4E0AE00490EF6 /* LeftVariable */ = { isa = PBXGroup; children = ( + 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */, + 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */, 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, ); @@ -993,7 +1024,7 @@ D22B38EC23F4E10700490EF6 /* SectionDividers */ = { isa = PBXGroup; children = ( - AA84562523FBB4770013B068 /* FourColumn */, + 52267A0523FFE0A900906CBA /* OneColumn */, D22B38ED23F4E11100490EF6 /* ThreeColumn */, ); path = SectionDividers; @@ -1116,7 +1147,8 @@ D224798E2316A995003FCCF9 /* HorizontalCombinationViews */, D224798D2316A988003FCCF9 /* VerticalCombinationViews */, 01EB368C23609801006832FA /* HeaderModel.swift */, - D2A514662213885800345BFB /* HeaderView.swift */, + D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */, + D2A514662213885800345BFB /* MoleculeHeaderView.swift */, 012A88EB238F084D00FE3DA1 /* FooterModel.swift */, D274CA322236A78900B01B62 /* FooterView.swift */, 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */, @@ -1630,6 +1662,7 @@ DBC4391922442197001AB423 /* DashLine.swift in Sources */, 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */, + AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */, 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */, @@ -1644,7 +1677,6 @@ 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 */, @@ -1652,6 +1684,7 @@ DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */, D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */, 017BEB442362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift in Sources */, + 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */, 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */, 9445891F2385D2E900DE9FD4 /* CaretViewModel.swift in Sources */, 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */, @@ -1675,6 +1708,7 @@ D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */, D28A838D23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift in Sources */, D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, + C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, @@ -1692,6 +1726,7 @@ D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */, 0A21DB85235E06EF00C160A2 /* MFTextField.m in Sources */, 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */, + AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */, 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */, 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */, D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, @@ -1701,7 +1736,7 @@ D2E2A99C23D8D975000B42E6 /* ImageHeadlineBodyModel.swift in Sources */, D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */, 012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */, - D2A514672213885800345BFB /* HeaderView.swift in Sources */, + D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */, D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */, D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */, @@ -1757,6 +1792,7 @@ 014AA72423C501E2006F3E93 /* MoleculeContainerModel.swift in Sources */, D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */, 011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */, + 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */, 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */, 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */, D2E2A99623D8CF85000B42E6 /* HeadlineBodyLinkToggleModel.swift in Sources */, @@ -1766,16 +1802,19 @@ D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, 8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */, D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */, + D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */, 012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */, D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */, D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */, D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */, D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */, + C7F8012123E8303200396FBD /* ListRVWheel.swift in Sources */, D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */, D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */, D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */, + 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */, 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */, D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, @@ -1785,6 +1824,7 @@ D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */, 017BEB4223620AD20024EF95 /* FormModelProtocol.swift in Sources */, + D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */, 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */, @@ -1830,6 +1870,7 @@ 012A88F123985E0100FE3DA1 /* Color.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */, + 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */, C003506123AA94CD00B6AC29 /* Button.swift in Sources */, DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */, 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */, @@ -1843,7 +1884,6 @@ 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/Atoms/Buttons/CaretLinkModel.swift b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift index defe6816..4ea79ef8 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift @@ -15,7 +15,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol { public var title: String public var action: ActionModelProtocol public var enabledColor: Color = Color(uiColor: .black) - public var disabledColor: Color? = Color(uiColor: .mfSilver()) + public var disabledColor: Color? = Color(uiColor: .mvmCoolGray6) public var enabled = true public init(title: String, action: ActionModelProtocol) { @@ -30,6 +30,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol { case enabledColor case disabledColor case enabled + case moleculeName } required public init(from decoder: Decoder) throws { @@ -50,6 +51,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(title, forKey: .title) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModel(action, forKey: .action) diff --git a/MVMCoreUI/Atoms/Buttons/Link.swift b/MVMCoreUI/Atoms/Buttons/Link.swift index b4c00c94..5dbbed16 100644 --- a/MVMCoreUI/Atoms/Buttons/Link.swift +++ b/MVMCoreUI/Atoms/Buttons/Link.swift @@ -36,6 +36,10 @@ import UIKit context?.strokePath() } + //-------------------------------------------------- + // MARK: - ModelMoleculeViewProtocol + //-------------------------------------------------- + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? LinkModel else { return } diff --git a/MVMCoreUI/Atoms/Buttons/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/LinkModel.swift index f4fab34c..7094a038 100644 --- a/MVMCoreUI/Atoms/Buttons/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/LinkModel.swift @@ -9,7 +9,12 @@ import UIKit public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "link" + public var backgroundColor: Color? public var title: String public var action: ActionModelProtocol @@ -17,12 +22,21 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { public var textColor = Color(uiColor: .mvmBlack) public var disabledColor = Color(uiColor: .mvmCoolGray6) + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(title: String, action: ActionModelProtocol) { self.title = title self.action = action } + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case title case action @@ -31,11 +45,16 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { case disabledColor } + //-------------------------------------------------- + // 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) title = try typeContainer.decode(String.self, forKey: .title) action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } @@ -51,6 +70,7 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(title, forKey: .title) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModel(action, forKey: .action) try container.encode(enabled, forKey: .enabled) diff --git a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift index e6e7cb24..496625dc 100644 --- a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift @@ -37,9 +37,9 @@ } public override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(caretView, forKey: .caretView) } } diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index 1030fb8c..e4a794bc 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -19,7 +19,6 @@ import Foundation } public var backgroundColor: Color? - public var moleculeName: String? public var title: String? public var feedback: String? public var errorMessage: String = "" @@ -54,7 +53,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decodeIfPresent(String.self, forKey: .title) feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) diff --git a/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift b/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift index 6caa70b0..e26995d6 100644 --- a/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift @@ -12,7 +12,7 @@ import UIKit public static var identifier: String = "textField" public var backgroundColor: Color? - public var moleculeName: String + public var moleculeName: String? = TextFieldModel.identifier public var editable: Bool? public var disabled: Bool? public var errorMsg: String? diff --git a/MVMCoreUI/Atoms/Views/CaretViewModel.swift b/MVMCoreUI/Atoms/Views/CaretViewModel.swift index 58291984..cf90496f 100644 --- a/MVMCoreUI/Atoms/Views/CaretViewModel.swift +++ b/MVMCoreUI/Atoms/Views/CaretViewModel.swift @@ -18,6 +18,7 @@ import Foundation public var lineWidth: CGFloat? private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case strokeColor case isHidden @@ -38,6 +39,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(strokeColor, forKey: .strokeColor) try container.encodeIfPresent(isHidden, forKey: .isHidden) try container.encodeIfPresent(isOpaque, forKey: .isOpaque) diff --git a/MVMCoreUI/Atoms/Views/CheckboxModel.swift b/MVMCoreUI/Atoms/Views/CheckboxModel.swift index aa5dedb4..706597ff 100644 --- a/MVMCoreUI/Atoms/Views/CheckboxModel.swift +++ b/MVMCoreUI/Atoms/Views/CheckboxModel.swift @@ -39,6 +39,7 @@ import Foundation //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case moleculeName case groupName case value case fieldKey @@ -57,6 +58,8 @@ import Foundation case isEnabled case action } + + init(isChecked: Bool = false) {} //-------------------------------------------------- // MARK: - Codec @@ -85,6 +88,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(value, forKey: .value) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) diff --git a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift index c4f55bef..2fc67b44 100644 --- a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift +++ b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift @@ -37,7 +37,10 @@ public class CircleProgressModel: MoleculeModelProtocol { public var colors = [Color]() public var backgroundColor: Color? - public init() {} + public init() { + updateStyle() + updateSize() + } private enum CodingKeys: String, CodingKey { case style @@ -48,6 +51,7 @@ public class CircleProgressModel: MoleculeModelProtocol { case duration case colors case backgroundColor + case moleculeName } required public init(from decoder: Decoder) throws { @@ -55,9 +59,11 @@ public class CircleProgressModel: MoleculeModelProtocol { if let style = try typeContainer.decodeIfPresent(GraphStyle.self, forKey: .style) { self.style = style } + updateStyle() if let size = try typeContainer.decodeIfPresent(GraphSize.self, forKey: .size) { self.size = size } + updateSize() if let diameter = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .diameter) { self.diameter = diameter } @@ -78,6 +84,7 @@ public class CircleProgressModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(style, forKey: .style) try container.encode(size, forKey: .size) try container.encode(diameter, forKey: .diameter) diff --git a/MVMCoreUI/Atoms/Views/DashLineModel.swift b/MVMCoreUI/Atoms/Views/DashLineModel.swift index 1346b5c2..7f5ac992 100644 --- a/MVMCoreUI/Atoms/Views/DashLineModel.swift +++ b/MVMCoreUI/Atoms/Views/DashLineModel.swift @@ -20,6 +20,7 @@ import Foundation } private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case dashColor case isHidden @@ -36,6 +37,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(dashColor, forKey: .dashColor) try container.encodeIfPresent(isHidden, forKey: .isHidden) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atoms/Views/ImageViewModel.swift index 97f31ad2..0f585119 100644 --- a/MVMCoreUI/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atoms/Views/ImageViewModel.swift @@ -11,6 +11,7 @@ import Foundation @objcMembers public class ImageViewModel: MoleculeModelProtocol { public static var identifier: String = "image" public var backgroundColor: Color? + public var moleculeName: String? = ImageViewModel.identifier public var image: String public var accessibilityText: String? public var fallbackImage: String? @@ -18,8 +19,21 @@ import Foundation public var width: CGFloat? public var height: CGFloat? public var contentMode: UIView.ContentMode? - + public var localBundle: Bundle? + public init(image: String) { self.image = image } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case image + case accessibilityText + case fallbackImage + case imageFormat + case width + case height + case contentMode + } } diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index 013f7f11..f08d532d 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -231,6 +231,7 @@ public typealias ActionBlock = () -> () attributedText = nil originalAttributedString = nil text = labelModel.text + hero = labelModel.hero Label.setLabel(self, withHTML: labelModel.html) let alignment = LabelAlignment(rawValue: labelModel.textAlignment ?? "") @@ -344,7 +345,6 @@ public typealias ActionBlock = () -> () } attributedText = attributedString originalAttributedString = attributedText - hero = labelModel.hero } } @@ -716,6 +716,7 @@ extension Label { public func reset() { text = nil attributedText = nil + hero = nil textAlignment = .left originalAttributedString = nil styleB2(true) @@ -807,9 +808,6 @@ extension Label { - Attention: This method expects text to be set first. Otherwise, it will do nothing. - parameter range: The range of text to be tapped. - - parameter actionMap: - - parameter delegate: - - parameter additionalData: */ @objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) { diff --git a/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift index 2ebcb4b4..503f00d8 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift @@ -8,12 +8,21 @@ import UIKit -class LabelAttributeActionModel: LabelAttributeModel { +open class LabelAttributeActionModel: LabelAttributeModel { override public class var identifier: String { return "action" } var action: ActionModelProtocol + public init(_ location: Int, _ length: Int, action: ActionModelProtocol) { + self.action = action + super.init(location, length) + } + + private enum CodingKeys: String, CodingKey { + case action + } + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) @@ -25,8 +34,4 @@ class LabelAttributeActionModel: LabelAttributeModel { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeModel(action, forKey: .action) } - - private enum CodingKeys: String, CodingKey { - case action - } } diff --git a/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift index 3c073b2f..437ec0cc 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift @@ -25,12 +25,14 @@ import Foundation return "" } - var type: String + var type: String { + get { return Self.identifier } + } + var location: Int var length: Int - init(_ type: String, _ location: Int, _ length: Int) { - self.type = type + init(_ location: Int, _ length: Int) { self.location = location self.length = length } @@ -51,7 +53,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - type = try typeContainer.decode(String.self, forKey: .type) location = try typeContainer.decode(Int.self, forKey: .location) length = try typeContainer.decode(Int.self, forKey: .length) } diff --git a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift index d7fb4fa3..cb9cc0a9 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift @@ -10,6 +10,10 @@ import Foundation @objcMembers public class LabelModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "label" public var backgroundColor: Color? public var text: String @@ -24,6 +28,10 @@ import Foundation public var hero: Int? public var makeWholeViewClickable: Bool? + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { case moleculeName case text @@ -43,11 +51,19 @@ import Foundation enum AttributeTypeKey: String, CodingKey { case type } - + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(text: String) { self.text = text } - + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) text = try typeContainer.decode(String.self, forKey: .text) diff --git a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift index 325611ec..d7ee1553 100644 --- a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift +++ b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift @@ -10,7 +10,12 @@ import UIKit @objcMembers public class LeftRightLabelModel: MoleculeModelProtocol { public static var identifier: String = "leftRightLabelView" + public var moleculeName: String? = LeftRightLabelModel.identifier public var backgroundColor: Color? public var leftText: LabelModel public var rightText: LabelModel? + + init(_ leftText: LabelModel) { + self.leftText = leftText + } } diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index 5e8cedc8..0079d1a6 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -210,6 +210,9 @@ import UIKit } public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + self.delegateObject = delegateObject + // TODO: Temporary, should be moved to init once we have type erasure ready. + setAsMolecule() guard let imageModel = model as? ImageViewModel else { return } @@ -230,7 +233,7 @@ import UIKit if shouldLoadImage(withName: imageModel.image, width: width, height: height) { imageView.image = nil imageView.animatedImage = nil - loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage) + loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage, localBundle: imageModel.localBundle) } if let contentMode = imageModel.contentMode { @@ -273,7 +276,9 @@ import UIKit } // MARK: - load functions - public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?, completionHandler: @escaping MVMCoreGetImageBlock) { + public func loadImage(withName imageName: String?, format: String? = nil, width: NSNumber? = nil, height: NSNumber? = nil, customFallbackImage: String? = nil, allowServerParameters: Bool = false, localBundle: Bundle? = nil, completionHandler: MVMCoreGetImageBlock? = nil) { + + let completionBlock = completionHandler ?? defaultCompletionBlock() MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in self.currentImageName = imageName self.currentImageWidth = width?.cgfloat() @@ -295,15 +300,15 @@ import UIKit if layoutWillChange { self?.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self!) } - completionHandler(image,data,isFallbackImage) + completionBlock(image,data,isFallbackImage) })} let fallbackImageName = customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback") if let format = format, format.lowercased().contains("gif") { // Gifs aren't supported by default and need special handling - MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, completionHandler: finishedLoadingBlock) + MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, completionHandler: finishedLoadingBlock) } else { - MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, completionHandler: finishedLoadingBlock) + MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock) } }) } @@ -333,6 +338,8 @@ import UIKit }) } + // Note: Exposed for objective-c interfaces. + public func loadImage(withName imageName: String?) { loadImage(withName: imageName, format: nil, width: nil, height: nil, customFallbackImage: nil, completionHandler: defaultCompletionBlock()) } @@ -368,4 +375,8 @@ import UIKit public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?) { loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: customFallbackImage, completionHandler: defaultCompletionBlock()) } + + public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?, completionHandler: @escaping MVMCoreGetImageBlock) { + loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: customFallbackImage, allowServerParameters: false, completionHandler: completionHandler) + } } diff --git a/MVMCoreUI/Atoms/Views/MultiProgressModel.swift b/MVMCoreUI/Atoms/Views/MultiProgressModel.swift index 6dd05b0b..4033fd28 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgressModel.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgressModel.swift @@ -26,6 +26,7 @@ import Foundation public var roundedRect: Bool? private enum CodingKeys: String, CodingKey { + case moleculeName case progressList case thickness case roundedRect @@ -46,6 +47,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(progressList, forKey: .progressList) try container.encodeIfPresent(thickness, forKey: .thickness) try container.encodeIfPresent(roundedRect, forKey: .roundedRect) diff --git a/MVMCoreUI/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atoms/Views/ToggleModel.swift index 9cd96f45..aafacec8 100644 --- a/MVMCoreUI/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atoms/Views/ToggleModel.swift @@ -10,7 +10,6 @@ import UIKit public class ToggleModel: MoleculeModelProtocol { public static var identifier: String = "toggle" - public var moleculeName: String? public var backgroundColor: Color? public var state: Bool = true public var action: ActionModelProtocol? diff --git a/MVMCoreUI/BaseClasses/Button.swift b/MVMCoreUI/BaseClasses/Button.swift index 60e0ab1a..c0ff0e81 100644 --- a/MVMCoreUI/BaseClasses/Button.swift +++ b/MVMCoreUI/BaseClasses/Button.swift @@ -12,6 +12,7 @@ public typealias ButtonAction = (Button) -> () //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- + open var model: MoleculeModelProtocol? open var actionModel: ActionModelProtocol? @@ -67,7 +68,7 @@ public typealias ButtonAction = (Button) -> () addTarget(self, action: #selector(callActionBlock(_:)), for: event) } - @objc private func callActionBlock(_ sender: Button) { + @objc func callActionBlock(_ sender: Button) { buttonAction?(self) } @@ -88,11 +89,13 @@ public typealias ButtonAction = (Button) -> () // MARK:- ModelMoleculeViewProtocol open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.model = model + if let backgroundColor = model?.backgroundColor { self.backgroundColor = backgroundColor.uiColor } guard let model = model as? ButtonModelProtocol else { return } + isEnabled = model.enabled set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } @@ -113,7 +116,7 @@ public typealias ButtonAction = (Button) -> () // MARK: - MVMCoreViewProtocol extension Button: MVMCoreViewProtocol { - open func updateView(_ size: CGFloat) {} + open func updateView(_ size: CGFloat) { } /// Will be called only once. open func setupView() { @@ -126,6 +129,7 @@ extension Button: MVMCoreViewProtocol { // MARK: - MVMCoreUIMoleculeViewProtocol extension Button: MVMCoreUIMoleculeViewProtocol { + open func reset() { backgroundColor = .clear } @@ -133,6 +137,7 @@ extension Button: MVMCoreUIMoleculeViewProtocol { // MARK: AppleGuidelinesProtocol extension Button: AppleGuidelinesProtocol { + override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return Self.acceptablyOutsideBounds(point: point, bounds: bounds) } diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index fe06a05a..d96a4587 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -139,7 +139,6 @@ import UIKit topSeparatorView?.updateView(size) bottomSeparatorView?.updateView(size) - molecule?.updateView(size) } @@ -153,9 +152,7 @@ import UIKit //TODO: Model, Change to model public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let model = model as? ListItemModelProtocol else { - return - } + guard let model = model as? ListItemModelProtocol else { return } self.listItemModel = model style(with: model.style) @@ -194,20 +191,21 @@ import UIKit return nil } - // MARK: - Arrow + // MARK: - Caret View /// Adds the standard mvm style caret to the accessory view @objc public func addCaretViewAccessory() { guard accessoryView == nil else { return } - caretView = CaretView(lineWidth: 1) - caretView?.translatesAutoresizingMaskIntoConstraints = true - caretView?.size = .small(.vertical) - caretView?.setConstraints() - if let size = caretView?.size?.dimensions() { + let caret = CaretView(lineWidth: 1) + caret.translatesAutoresizingMaskIntoConstraints = true + caret.size = .small(.vertical) + if let size = caret.size?.dimensions() { + caret.frame = CGRect(origin: CGPoint.zero, size: size) caretViewWidthSizeObject = MFSizeObject(standardSize: size.width, standardiPadPortraitSize: 9) caretViewHeightSizeObject = MFSizeObject(standardSize: size.height, standardiPadPortraitSize: 16) } - accessoryView = caretView + caretView = caret + accessoryView = caret } /// NOTE: Should only be called when displayed or about to be displayed. @@ -217,11 +215,11 @@ import UIKit layoutIfNeeded() guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return } let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel) - accessoryView?.center.y = contentView.convert(UIView(frame: rect).center, from: heroLabel).y + accessoryView?.center.y = convert(UIView(frame: rect).center, from: heroLabel).y heroAccessoryCenter = accessoryView?.center } - /// Traverses the view hierarchy for a 🦸‍♂️heroic Label. + /// Traverses the view hierarchy for a 🦸‍♂️ heroic Label. private func findHeroLabel(views: [UIView]) -> Label? { if views.isEmpty { diff --git a/MVMCoreUI/BaseControllers/MFViewController+Model.swift b/MVMCoreUI/BaseControllers/MFViewController+Model.swift index 1ddbd4ab..e70e68f6 100644 --- a/MVMCoreUI/BaseControllers/MFViewController+Model.swift +++ b/MVMCoreUI/BaseControllers/MFViewController+Model.swift @@ -37,7 +37,3 @@ extension MFViewController: MoleculeDelegateProtocol { @objc public func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { } } - -public extension MFViewController { - @objc func parsePageJSON() throws { } -} diff --git a/MVMCoreUI/BaseControllers/MFViewController.h b/MVMCoreUI/BaseControllers/MFViewController.h index cd96a07f..38ced354 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.h +++ b/MVMCoreUI/BaseControllers/MFViewController.h @@ -96,6 +96,9 @@ // This view controller should subclass this function and check the load to make sure it has all the needed data. Fills the error object if there are any errors. Returns if we should finish the load or not. - (BOOL)shouldFinishProcessingLoad:(nonnull MVMCoreLoadObject *)loadObject error:(MVMCoreErrorObject *_Nonnull *_Nonnull)error; +/// Called in newDataBuildScreen. Can override to parse the json into a model object. +- (void)parsePageJSON:(NSError * _Nullable * _Nullable)error; + // Sets the screen to use the screen heading. // it is required in device flow, where we are showing greeting name as screen heading, // device details screen heading needs to be updated/refreshed again, if user has changed device nick name diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/BaseControllers/MFViewController.m index 09700268..f663193f 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.m +++ b/MVMCoreUI/BaseControllers/MFViewController.m @@ -98,7 +98,7 @@ self.loadObject = loadObject; NSError *parseError = nil; - [self parsePageJSONAndReturnError:&parseError]; + [self parsePageJSON:&parseError]; if (parseError) { if (error) { MVMCoreErrorObject *errorObject = [MVMCoreErrorObject createErrorObjectForNSError:parseError location:[[MVMCoreLoadHandler sharedGlobal] errorLocationForRequest:loadObject]]; @@ -112,6 +112,10 @@ return [MFViewController verifyRequiredModulesLoadedForLoadObject:loadObject error:error]; } +- (void)parsePageJSON:(NSError * _Nullable * _Nullable)error { + +} + // Sets the screen to use the screen heading. // it is required in device flow, where we are showing greeting name as screen heading, // device details screen heading needs to be updated/refreshed again, if user has changed device nick name @@ -261,7 +265,7 @@ - (BOOL)newPageLoaded:(nonnull NSDictionary *)page { self.loadObject.pageJSON = page; NSError *parseError = nil; - [self parsePageJSONAndReturnError:&parseError]; + [self parsePageJSON:&parseError]; return YES; } diff --git a/MVMCoreUI/Containers/Views/Container/ContainerModel.swift b/MVMCoreUI/Containers/Views/Container/ContainerModel.swift index cdc6d743..a5e89adb 100644 --- a/MVMCoreUI/Containers/Views/Container/ContainerModel.swift +++ b/MVMCoreUI/Containers/Views/Container/ContainerModel.swift @@ -27,6 +27,12 @@ public class ContainerModel: ContainerModelProtocol, Codable { } public init() {} + + public convenience init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil) { + self.init() + self.horizontalAlignment = horizontalAlignment + self.verticalAlignment = verticalAlignment + } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) diff --git a/MVMCoreUI/Containers/Views/MoleculeContainer.swift b/MVMCoreUI/Containers/Views/MoleculeContainer.swift index 9a907222..d179ef72 100644 --- a/MVMCoreUI/Containers/Views/MoleculeContainer.swift +++ b/MVMCoreUI/Containers/Views/MoleculeContainer.swift @@ -31,7 +31,7 @@ open class MoleculeContainer: Container { } public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - if let casteModel = model as? MoleculeContainerModel { + if let casteModel = model as? MoleculeContainerModelProtocol { if view != nil { (view as? ModelMoleculeViewProtocol)?.setWithModel(casteModel.molecule, delegateObject, additionalData) } else { @@ -44,7 +44,7 @@ open class MoleculeContainer: Container { } public override static func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - guard let containerModel = model as? MoleculeContainerModel, + 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")<>" @@ -53,7 +53,7 @@ open class MoleculeContainer: Container { } public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - guard let containerModel = molecule as? MoleculeContainerModel else { return 0 } + guard let containerModel = molecule 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 { return (containerModel.topMarginPadding ?? 0) + (containerModel.bottomMarginPadding ?? 0) @@ -62,7 +62,7 @@ open class MoleculeContainer: Container { } public override class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let containerModel = molecule as? MoleculeContainerModel, + guard let containerModel = molecule as? MoleculeContainerModelProtocol, let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(containerModel.molecule) as? ModelMoleculeViewProtocol.Type else { return nil } return moleculeClass.requiredModules(containerModel.molecule, delegateObject: delegateObject, error: error) } diff --git a/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift b/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift index 0421b3d1..95683f8f 100644 --- a/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift +++ b/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift @@ -8,7 +8,7 @@ import Foundation -public class MoleculeContainerModel: ContainerModel { +public class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol { public var molecule: MoleculeModelProtocol private enum CodingKeys: String, CodingKey { diff --git a/MVMCoreUI/Containers/Views/MoleculeContainerProtocol.swift b/MVMCoreUI/Containers/Views/MoleculeContainerProtocol.swift new file mode 100644 index 00000000..882cf181 --- /dev/null +++ b/MVMCoreUI/Containers/Views/MoleculeContainerProtocol.swift @@ -0,0 +1,13 @@ +// +// MoleculeContainerProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 2/24/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol MoleculeContainerModelProtocol: ContainerModelProtocol { + var molecule: MoleculeModelProtocol { get set } +} diff --git a/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift index 1ec0d13c..cec7b90a 100644 --- a/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift @@ -3,7 +3,7 @@ import Foundation public protocol MoleculeModelProtocol: Model { var moleculeName: String? { get } - var backgroundColor: Color? { get set} + var backgroundColor: Color? { get set } } public extension MoleculeModelProtocol { diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift new file mode 100644 index 00000000..0dad7228 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift @@ -0,0 +1,40 @@ +// +// ListLeftVariableCheckboxAllTextAndLinks.swift +// MVMCoreUI +// +// Created by Lekshmi S on 11/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +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) + + // 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? { + return 140 + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift new file mode 100644 index 00000000..fec71c0b --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift @@ -0,0 +1,42 @@ +// +// ListLeftVariableCheckboxAllTextAndLinksModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 11/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListLeftVariableCheckboxAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { + public static var identifier: String = "listLVCB" + public var checkbox: CheckboxModel + public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + + public init(checkbox: CheckboxModel, eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel) { + self.checkbox = checkbox + self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink + super.init() + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case eyebrowHeadlineBodyLink + case checkbox + } + + 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 { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) + try container.encode(checkbox, forKey: .checkbox) + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift index 9f0e2deb..058d0da3 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift @@ -9,7 +9,7 @@ import Foundation import UIKit -@objcMembers public class ListLeftVariableIconWithRightCaret: TableViewCell { +@objcMembers open class ListLeftVariableIconWithRightCaret: TableViewCell { //----------------------------------------------------- // MARK: - Outlets @@ -22,17 +22,11 @@ import UIKit //----------------------------------------------------- // MARK: - View Lifecycle //------------------------------------------------------- - open override func updateView(_ size: CGFloat) { - super.updateView(size) - stack.updateView(size) - } override open func setupView() { super.setupView() - stack.translatesAutoresizingMaskIntoConstraints = false stack.stackItems = [StackItem(andContain: leftImage),StackItem(andContain: leftLabel),StackItem(andContain: rightLabel)] - contentView.addSubview(stack) - containerHelper.constrainView(stack) + addMolecule(stack) leftLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal) rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal) } @@ -40,32 +34,28 @@ import UIKit //---------------------------------------------------- // MARK: - Molecule //------------------------------------------------------ - override open func reset() { - super.reset() - stack.reset() - } - - 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? ListLeftVariableIconWithRightCaretModel else { return} leftImage.setWithModel(model.image, delegateObject, additionalData) leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) - // Create a stack model to use for the internal stack and set the alignment of labels - let leftImage = StackItemModel() - leftImage.horizontalAlignment = .fill - let leftLabel = StackItemModel() - leftLabel.horizontalAlignment = .fill - let rightLabel = StackItemModel() - rightLabel.horizontalAlignment = .trailing - let stackModel = StackModel(molecules: [leftImage,leftLabel,rightLabel]) - stackModel.axis = .horizontal + let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill), + StackItemModel(horizontalAlignment: .fill), + StackItemModel(horizontalAlignment: .trailing)], + axis: .horizontal) stack.model = stackModel stack.restack() } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 90 } + + open override func reset() { + super.reset() + leftLabel.styleB2(true) + rightLabel.styleB2(true) + } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretModel.swift index bccf5320..4b426909 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretModel.swift @@ -19,6 +19,7 @@ public class ListLeftVariableIconWithRightCaretModel: ListItemModel, MoleculeMod if image.height == nil { image.height = 30.0 } + rightLabel.hero = 0 } public init(image: ImageViewModel, leftLabel: LabelModel, rightLabel: LabelModel) { @@ -43,7 +44,7 @@ public class ListLeftVariableIconWithRightCaretModel: ListItemModel, MoleculeMod try super.init(from: decoder) } - public override func encode(to encoder: Encoder) throws { + public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift new file mode 100644 index 00000000..46d4b955 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift @@ -0,0 +1,56 @@ +// +// ListRVWheel.swift +// MVMCoreUI +// +// Created by Arora, Prateek on 20/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +@objcMembers open class ListRVWheel: TableViewCell { + let wheel = GraphView(frame: .zero) + let leftLabel = Label.commonLabelB1(true) + let rightLabel = Label.commonLabelB2(true) + let stack = Stack(frame: .zero) + + //------------------------------------------------- + // MARK: - Setup + //------------------------------------------------- + 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) + } + + //------------------------------------------------- + // MARK: - ModelMoleculeViewProtocol + //------------------------------------------------- + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(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() + } + + //------------------------------------------------- + // MARK: - MVMCoreUIMoleculeViewProtocol + //------------------------------------------------- + open override func reset() { + super.reset() + leftLabel.styleB1(true) + rightLabel.styleB2(true) + } + + public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 70 + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift new file mode 100644 index 00000000..89b70b0f --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift @@ -0,0 +1,52 @@ +// +// ListRVWheelModel.swift +// MVMCoreUI +// +// Created by Arora, Prateek on 03/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol { + public static var identifier: String = "listRVWheel" + public var leftLabel: LabelModel + public var rightLabel: LabelModel + public var wheel : CircleProgressModel + + public init(leftLabel: LabelModel, rightLabel: LabelModel, wheel: CircleProgressModel) { + self.leftLabel = leftLabel + self.rightLabel = rightLabel + self.wheel = wheel + super.init() + } + + /// Defaults to set + override public func setDefaults() { + super.setDefaults() + rightLabel.hero = 0 + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case leftLabel + case rightLabel + case wheel + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) + rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) + wheel = try typeContainer.decodeIfPresent(CircleProgressModel.self, forKey: .wheel) ?? CircleProgressModel() + 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(leftLabel, forKey: .leftLabel) + try container.encode(rightLabel, forKey: .rightLabel) + try container.encode(wheel, forKey: .wheel) + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift new file mode 100644 index 00000000..66f88371 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -0,0 +1,53 @@ +// +// ListRightVariablePayments.swift +// MVMCoreUI +// +// Created by Lekshmi S on 10/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class ListRightVariablePayments: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //------------------------------------------------------- + let leftLabel = Label.commonLabelB1(true) + let rightImage = MFLoadImageView(pinnedEdges: .all) + let stack = Stack(frame: .zero) + + //----------------------------------------------------- + // MARK: - View Lifecycle + //------------------------------------------------------- + override open func setupView() { + super.setupView() + stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)] + 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? 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() + } + + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 65 + } + + open override func reset() { + super.reset() + leftLabel.styleB1(true) + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift new file mode 100644 index 00000000..4842b60a --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -0,0 +1,58 @@ +// +// ListRightVariablePaymentsModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 10/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtocol { + + public static var identifier: String = "listRVImg" + public var image: ImageViewModel + public var leftLabel: LabelModel + + public init(image: ImageViewModel, leftLabel: LabelModel) { + self.leftLabel = leftLabel + self.image = image + super.init() + } + + /// Defaults to set + override public func setDefaults() { + super.setDefaults() + leftLabel.hero = 0 + } + + static func createPayPalImage() -> ImageViewModel { + let image = ImageViewModel(image: "imageName_PayPal_logo") + image.localBundle = MVMCoreUIUtility.bundleForMVMCoreUI() + image.width = 70.0 + image.height = 18.0 + image.contentMode = .scaleAspectFit + return image + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case leftLabel + case image + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) + image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image) ?? ListRightVariablePaymentsModel.createPayPalImage() + 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(leftLabel, forKey: .leftLabel) + try container.encode(image, forKey: .image) + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift new file mode 100644 index 00000000..9e930396 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -0,0 +1,65 @@ +// +// 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(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)]) + 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/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift new file mode 100644 index 00000000..47e482a0 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift @@ -0,0 +1,57 @@ +// +// ListOneColumnFullWidthTextAllTextAndLinksModel.swift +// MVMCoreUI +// +// Created by Kruthika KP on 14/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListOneColumnFullWidthTextAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { + public static var identifier: String = "list1CTxt" + public var eyebrow: LabelModel? + public var headline : LabelModel? + public var subHeadline: LabelModel? + public var body: LabelModel? + public var link : LinkModel? + + public init(eyebrow: LabelModel? = nil, headline: LabelModel? = nil, subHeadline: LabelModel? = nil, body: LabelModel? = nil, link: LinkModel? = nil) { + self.eyebrow = eyebrow + self.headline = headline + self.subHeadline = subHeadline + self.body = body + self.link = link + super.init() + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case eyebrow + case headline + case subHeadline + case body + case link + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) + headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline) + subHeadline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .subHeadline) + body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) + link = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .link) + 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(eyebrow, forKey: .eyebrow) + try container.encodeIfPresent(headline, forKey: .headline) + try container.encodeIfPresent(subHeadline, forKey: .subHeadline) + try container.encodeIfPresent(body, forKey: .body) + try container.encodeIfPresent(link, forKey: .link) + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift index 19774110..565ed737 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift @@ -16,23 +16,16 @@ import Foundation let stack = Stack(frame: .zero) // MARK: - MFViewProtocol - open override func updateView(_ size: CGFloat) { - super.updateView(size) - stack.updateView(size) - } - open override func setupView() { super.setupView() //using stackItems to align the three headlineBody - stack.translatesAutoresizingMaskIntoConstraints = false stack.stackItems = [StackItem(andContain: leftHeadlineBody),StackItem(andContain: centerHeadLineBody),StackItem(andContain: rightHeadLineBody)] - contentView.addSubview(stack) - containerHelper.constrainView(stack) + addMolecule(stack) } // MARK: - MVMCoreUIMoleculeViewProtocol - 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? ListThreeColumnPlanDataDividerModel else { return } leftHeadlineBody.setWithModel(model.leftHeadlineBody, delegateObject, additionalData) @@ -40,24 +33,15 @@ import Foundation rightHeadLineBody.setWithModel(model.rightHeadlineBody, delegateObject, additionalData) // Create a stack model to use for the internal stack and set the alignment of models - let leftHeadlineBodyAlignment = StackItemModel(percent: 33) - leftHeadlineBodyAlignment.horizontalAlignment = .leading - let centerHeadLineBodyAlignment = StackItemModel(percent: 34) - centerHeadLineBodyAlignment.horizontalAlignment = .center - let rightHeadLineBodyAlignment = StackItemModel(percent: 33) - rightHeadLineBodyAlignment.horizontalAlignment = .trailing - let stackModel = StackModel(molecules: [leftHeadlineBodyAlignment,centerHeadLineBodyAlignment,rightHeadLineBodyAlignment]) - stackModel.axis = .horizontal + 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() } - open override func reset() { - super.reset() - stack.reset() - } - - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { return 121 } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDividerModel.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDividerModel.swift index fd946eb0..3ddfe64b 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDividerModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDividerModel.swift @@ -26,6 +26,9 @@ public class ListThreeColumnPlanDataDividerModel: ListItemModel, MoleculeModelPr override public func setDefaults() { super.setDefaults() style = "tallDivider" + leftHeadlineBody.style = "itemHeader" + centerHeadlineBody.style = "itemHeader" + rightHeadlineBody.style = "itemHeader" } private enum CodingKeys: String, CodingKey { diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift index 42acd2f0..1e5c7dce 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift @@ -11,6 +11,7 @@ import Foundation @objcMembers public class DoughnutChartModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "doughnutChart" + public var moleculeName: String? = DoughnutChartModel.identifier public var title: LabelModel? public var subtitle: LabelModel? public var sections: [DoughnutChartItemModel] @@ -24,6 +25,7 @@ import Foundation @objcMembers public class DoughnutChartItemModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "doughnutChartItem" + public var moleculeName: String? = DoughnutChartItemModel.identifier public var label: LabelModel @Percent public var percent: CGFloat public var color: Color diff --git a/MVMCoreUI/Molecules/HeaderModel.swift b/MVMCoreUI/Molecules/HeaderModel.swift index b6f3629f..6314947c 100644 --- a/MVMCoreUI/Molecules/HeaderModel.swift +++ b/MVMCoreUI/Molecules/HeaderModel.swift @@ -8,19 +8,17 @@ import Foundation -@objcMembers public class HeaderModel: MoleculeContainerModel, MoleculeModelProtocol { - public static var identifier: String = "header" +@objcMembers public class HeaderModel: ContainerModel { public var backgroundColor: Color? public var line: LineModel? private enum CodingKeys: String, CodingKey { - case moleculeName case line case backgroundColor } /// Defaults to set - func setDefaults() { + public func setDefaults() { if useHorizontalMargins == nil { useHorizontalMargins = true } @@ -33,25 +31,27 @@ import Foundation if bottomMarginPadding == nil { bottomMarginPadding = PaddingDefaultVerticalSpacing } - line?.type = .heavy + if line == nil { + line = LineModel(type: .heavy) + } } - public override init(with moleculeModel: MoleculeModelProtocol) { - super.init(with: moleculeModel) + public override init() { + super.init() setDefaults() } required public init(from decoder: Decoder) throws { try super.init(from: decoder) - setDefaults() let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) ?? LineModel(type: .heavy) + line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + setDefaults() } 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(line, forKey: .line) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift index 4966ce58..7f3d52dc 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift @@ -10,6 +10,7 @@ import Foundation public struct ImageHeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "imageHeadlineBody" + public var moleculeName: String? = ImageHeadlineBodyModel.identifier public var backgroundColor: Color? public var image: ImageViewModel public var headlineBody: HeadlineBodyModel diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift index f45c771d..8b69c590 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -22,6 +22,7 @@ public class TabsModel: MoleculeModelProtocol { case backgroundColor case selectedColor case selectedIndex + case moleculeName } public init(with tabs: [LabelModel]) { @@ -42,6 +43,7 @@ public class TabsModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) try container.encode(backgroundColor, forKey: .backgroundColor) try container.encode(selectedColor, forKey: .selectedColor) diff --git a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift index f2c88e9b..9fc218a7 100644 --- a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift +++ b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift @@ -14,7 +14,6 @@ import Foundation public var backgroundColor: Color? public var peakingUI: Bool? public var peakingArrowColor: Color? - public var moleculeName: String? private enum CodingKeys: String, CodingKey { case moleculeName @@ -25,7 +24,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) peakingUI = try typeContainer.decodeIfPresent(Bool.self, forKey: .peakingUI) peakingArrowColor = try typeContainer.decodeIfPresent(Color.self, forKey: .peakingArrowColor) diff --git a/MVMCoreUI/Molecules/Items/StackItemModel.swift b/MVMCoreUI/Molecules/Items/StackItemModel.swift index 2058353c..795b2983 100644 --- a/MVMCoreUI/Molecules/Items/StackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/StackItemModel.swift @@ -10,18 +10,20 @@ import Foundation @objcMembers public class StackItemModel: ContainerModel, StackItemModelProtocol, MoleculeModelProtocol { public static var identifier: String = "simpleStackItem" + public var moleculeName: String? = StackItemModel.identifier public var backgroundColor: Color? public var spacing: CGFloat? public var percent: Int? public var gone: Bool = false - public convenience init(gone: Bool) { - self.init() - self.gone = gone - } - - public convenience init(percent: Int) { + public convenience init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) { self.init() + self.horizontalAlignment = horizontalAlignment + self.verticalAlignment = verticalAlignment + self.spacing = spacing self.percent = percent + if let gone = gone { + self.gone = gone + } } } diff --git a/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift index a397c1a1..9dbf53c0 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift @@ -10,6 +10,7 @@ import Foundation public struct ActionDetailWithImageModel: MoleculeModelProtocol { public static var identifier: String = "actionDetailWithImage" + public var moleculeName: String? = ActionDetailWithImageModel.identifier public var backgroundColor: Color? public var headlineBodyButton: HeadlineBodyButtonModel public var image: ImageViewModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift b/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift index f4b67216..bb3e6f17 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift @@ -28,6 +28,7 @@ public class CornerLabelsModel: MoleculeModelProtocol { case bottomLeftLabel case bottomRightLabel case molecule + case moleculeName } required public init(from decoder: Decoder) throws { @@ -48,5 +49,6 @@ public class CornerLabelsModel: MoleculeModelProtocol { try container.encodeIfPresent(topRightLabel, forKey: .topRightLabel) try container.encodeIfPresent(bottomLeftLabel, forKey: .bottomLeftLabel) try container.encodeIfPresent(bottomRightLabel, forKey: .bottomRightLabel) + try container.encode(moleculeName, forKey: .moleculeName) } } diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift index 5ce04f9c..aad8ec06 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift @@ -9,6 +9,7 @@ import Foundation public struct HeadlineBodyLinkToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLinkToggle" + public var moleculeName: String? = HeadlineBodyLinkToggleModel.identifier public var backgroundColor: Color? public var headlineBodyLink: HeadlineBodyLinkModel public var toggle: ToggleModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift index dd7c2b1c..bb3391a6 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift @@ -11,6 +11,7 @@ import Foundation open class HeadlineBodyToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyToggle" + public var moleculeName: String? = HeadlineBodyToggleModel.identifier open var backgroundColor: Color? open var headlineBody: HeadlineBodyModel open var toggle: ToggleModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift index 7ed5857e..526ac6b9 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift @@ -10,7 +10,13 @@ import Foundation public class LabelToggleModel: MoleculeModelProtocol { public static var identifier: String = "labelToggle" + public var moleculeName: String? = LabelToggleModel.identifier public var backgroundColor: Color? public var label: LabelModel public var toggle: ToggleModel + + init(_ label: LabelModel, _ toggle: ToggleModel) { + self.label = label + self.toggle = toggle + } } diff --git a/MVMCoreUI/Molecules/MoleculeHeaderModel.swift b/MVMCoreUI/Molecules/MoleculeHeaderModel.swift new file mode 100644 index 00000000..92958ca1 --- /dev/null +++ b/MVMCoreUI/Molecules/MoleculeHeaderModel.swift @@ -0,0 +1,37 @@ +// +// MoleculeHeaderModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 10/3/19. +// Copyright © 2019 Suresh, Kamlesh. All rights reserved. +// + +import Foundation + +@objcMembers public class MoleculeHeaderModel: HeaderModel, MoleculeModelProtocol, MoleculeContainerModelProtocol { + public static var identifier: String = "header" + public var molecule: MoleculeModelProtocol + + private enum CodingKeys: String, CodingKey { + case moleculeName + case molecule + } + + public init(with moleculeModel: MoleculeModelProtocol) { + molecule = moleculeModel + super.init() + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + molecule = try typeContainer.decodeMolecule(codingKey: .molecule) + 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.encodeModel(molecule, forKey: .molecule) + } +} diff --git a/MVMCoreUI/Molecules/HeaderView.swift b/MVMCoreUI/Molecules/MoleculeHeaderView.swift similarity index 60% rename from MVMCoreUI/Molecules/HeaderView.swift rename to MVMCoreUI/Molecules/MoleculeHeaderView.swift index c90be96d..5d58c675 100644 --- a/MVMCoreUI/Molecules/HeaderView.swift +++ b/MVMCoreUI/Molecules/MoleculeHeaderView.swift @@ -1,5 +1,5 @@ // -// HeaderView.swift +// MoleculeHeaderView.swift // MVMCoreUI // // Created by Scott Pfeil on 2/12/19. @@ -8,55 +8,41 @@ import UIKit -public class HeaderView: MoleculeContainer { - var line: Line? +public class MoleculeHeaderView: MoleculeContainer { + var line = Line() - var headerModel: HeaderModel? { - get { return model as? HeaderModel } + var headerModel: MoleculeHeaderModel? { + get { return model as? MoleculeHeaderModel } } // MARK: - MVMCoreViewProtocol open override func updateView(_ size: CGFloat) { super.updateView(size) - line?.updateView(size) + line.updateView(size) } public override func setupView() { super.setupView() - - guard line == nil else { return } - let line = Line() line.setStyle(.heavy) addSubview(line) NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true NSLayoutConstraint.pinViewRight(toSuperview: line, useMargins: true, constant: 0).isActive = true - self.line = line } // MARK: - MVMCoreUIMoleculeViewProtocol - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - if let separatorJSON = json?.optionalDictionaryForKey("line") { - line?.setWithJSON(separatorJSON, delegateObject: delegateObject, additionalData: additionalData) - } - } - - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) - - guard let headerModel = model as? HeaderModel else { - return - } - - if let seperatorModel = headerModel.line { - line?.setWithJSON(seperatorModel.toJSON(), delegateObject: delegateObject, additionalData: additionalData) - } - } - open override func reset() { super.reset() - line?.setStyle(.heavy) + line.setStyle(.heavy) + } + + // MARK: - ModelMoleculeViewProtocol + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let headerModel = headerModel else { return } + if let lineModel = headerModel.line { + line.setWithModel(lineModel, delegateObject, additionalData) + } } public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { diff --git a/MVMCoreUI/Molecules/ScrollerModel.swift b/MVMCoreUI/Molecules/ScrollerModel.swift index f92fe13b..91dc2e1c 100644 --- a/MVMCoreUI/Molecules/ScrollerModel.swift +++ b/MVMCoreUI/Molecules/ScrollerModel.swift @@ -10,5 +10,6 @@ import UIKit public class ScrollerModel: MoleculeContainerModel, MoleculeModelProtocol { public static var identifier: String = "scroller" + public var moleculeName: String? = ScrollerModel.identifier public var backgroundColor: Color? } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index ff8e6cfa..e9d7d34e 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -9,22 +9,30 @@ import UIKit @objcMembers open class EyebrowHeadlineBodyLink: Container { + //-------------------------------------------------- + // 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() + var casteModel: EyebrowHeadlineBodyLinkModel? { get { return model as? EyebrowHeadlineBodyLinkModel } } + //-------------------------------------------------- // MARK: - MFViewProtocol + //-------------------------------------------------- + open override func setupView() { super.setupView() - guard stack.superview == nil else { - return - } - stack.stackItems = [StackItem(andContain: eyebrow),StackItem(andContain: headline),StackItem(andContain: body),StackItem(andContain: link)] + stack.stackItems = [StackItem(andContain: eyebrow), + StackItem(andContain: headline), + StackItem(andContain: body), + StackItem(andContain: link)] addSubview(stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) } @@ -34,7 +42,10 @@ import UIKit stack.updateView(size) } + //-------------------------------------------------- // MARK: - MVMCoreUIMoleculeViewProtocol + //-------------------------------------------------- + open override func reset() { super.reset() stack.reset() @@ -44,16 +55,23 @@ import UIKit body.styleB2(true) } - // MARK:- ModelMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + //-------------------------------------------------- + // MARK: - ModelMoleculeViewProtocol + //-------------------------------------------------- + + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) - eyebrow.setWithModel(casteModel?.eyeBrow, 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) // 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)]) + 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 stack.restack() diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index e9341535..e277f5de 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -8,12 +8,84 @@ import Foundation -struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { - static var identifier: String = "eyebrowHeadlineBodyLink" - var backgroundColor: Color? - - public var eyeBrow: LabelModel? +public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public static var identifier: String = "eyebrowHeadlineBodyLink" + public var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier + public var backgroundColor: Color? + public var eyebrow: LabelModel? public var headline: LabelModel? public var body: LabelModel? public var link: LinkModel? + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + + public init(eyebrow: LabelModel? = nil, headline: LabelModel? = nil, body: LabelModel? = nil, link: LinkModel? = nil) throws { + // TODO: This class initializers should ensure that atleast one item is set. + /*guard eyebrow != nil || headline != nil || body != nil || link != nil else { + throw + }*/ + self.eyebrow = eyebrow + self.headline = headline + self.body = body + self.link = link + setDefaults() + } + + //-------------------------------------------------- + // MARK: - Method + //-------------------------------------------------- + + /// Defaults to set + public func setDefaults() { + if let headline = headline { + headline.hero = 0 + } + } + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case eyebrow + case headline + case body + case link + } + + //-------------------------------------------------- + // 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) + eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) + headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline) + body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) + link = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .link) + setDefaults() + // TODO: This class initializers should ensure that atleast one item is set. + /*guard eyebrow != nil || headline != nil || body != nil || link != nil else { + throw + }*/ + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(eyebrow, forKey: .eyebrow) + try container.encodeIfPresent(headline, forKey: .headline) + try container.encodeIfPresent(body, forKey: .body) + try container.encodeIfPresent(link, forKey: .link) + } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift index 74e85ea9..ec97fda0 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift @@ -10,6 +10,7 @@ import Foundation public struct HeadlineBodyButtonModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyButton" + public var moleculeName: String? = HeadlineBodyButtonModel.identifier public var backgroundColor: Color? public var headlineBody: HeadlineBodyModel diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift index 9eae8e03..27f0d670 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift @@ -10,6 +10,7 @@ import Foundation public struct HeadlineBodyLinkModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLink" + public var moleculeName: String? = HeadlineBodyLinkModel.identifier public var headlineBody: HeadlineBodyModel public var link: LinkModel public var backgroundColor: Color? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index fd5be23a..d7a08091 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -10,6 +10,7 @@ import Foundation @objcMembers public class HeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "headlineBody" + public var moleculeName: String? = HeadlineBodyModel.identifier public var headline: LabelModel? public var body: LabelModel? public var style: String? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift index caa00021..c66f27b8 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift @@ -38,5 +38,6 @@ public class StringAndMoleculeModel: MoleculeModelProtocol { try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(string, forKey: .string) try container.encodeModel(molecule, forKey: .molecule) + try container.encode(moleculeName, forKey: .moleculeName) } } diff --git a/MVMCoreUI/Organisms/CarouselModel.swift b/MVMCoreUI/Organisms/CarouselModel.swift index e43e6caa..79693135 100644 --- a/MVMCoreUI/Organisms/CarouselModel.swift +++ b/MVMCoreUI/Organisms/CarouselModel.swift @@ -53,7 +53,7 @@ import UIKit public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(moleculeName, forKey: .moleculeName) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(molecules, forKey: .molecules) try container.encode(spacing, forKey: .spacing) diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index 4e7a3114..602ab0f1 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -8,15 +8,24 @@ import Foundation + open class Stack: Container where T: StackModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + var contentView: UIView = MVMCoreUICommonViewsUtility.commonView() var stackModel: T? { get { return model as? T } } var stackItems: [UIView] = [] + //-------------------------------------------------- // MARK: - Helpers + //-------------------------------------------------- + public 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 constraint.isActive = true @@ -45,13 +54,16 @@ open class Stack: Container where T: StackModelProtocol { item.removeFromSuperview() } } + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- - // MARK: - Inits public override init(frame: CGRect) { super.init(frame: frame) } - public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.init(frame: CGRect.zero) setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) } @@ -60,12 +72,13 @@ open class Stack: Container where T: StackModelProtocol { fatalError("init(coder:) has not been implemented") } + //-------------------------------------------------- // MARK: - MFViewProtocol + //-------------------------------------------------- + public override func setupView() { super.setupView() - guard contentView.superview == nil else { - return - } + guard contentView.superview == nil else { return } MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0) translatesAutoresizingMaskIntoConstraints = false backgroundColor = .clear @@ -82,7 +95,10 @@ open class Stack: Container where T: StackModelProtocol { } } + //-------------------------------------------------- // MARK: - MVMCoreUIMoleculeViewProtocol + //-------------------------------------------------- + public override func reset() { super.reset() backgroundColor = .clear @@ -91,7 +107,7 @@ open class Stack: Container where T: StackModelProtocol { } } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { let previousModel = self.model super.setWithModel(model, delegateObject, additionalData) removeAllItemViews() @@ -132,6 +148,7 @@ open class Stack: Container where T: StackModelProtocol { guard let model = molecule 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 @@ -158,26 +175,31 @@ open class Stack: Container where T: StackModelProtocol { return modules.count > 0 ? modules : nil } + //-------------------------------------------------- // MARK: - Subclassables - + //-------------------------------------------------- + /// 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]?) { - } + 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]?) { + 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) } } + //-------------------------------------------------- // MARK: - Adding to stack + //-------------------------------------------------- + /// Gets the percent modifier. This value is used to help properly calculate percent for stack items when spacing is involved. private func getTotalSpace() -> CGFloat { guard let stackModel = stackModel else { return 0.0 } var totalSpace: CGFloat = 0.0 var firstMoleculeFound = false + for stackItemModel in stackModel.molecules { guard !stackItemModel.gone else { continue } let spacing = stackItemModel.spacing ?? stackModel.spacing @@ -222,7 +244,7 @@ open class Stack: Container where T: StackModelProtocol { pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0) if let percent = model.percent { - let multiplier = CGFloat(percent)/100.0 + let multiplier = CGFloat(percent) / 100.0 let constant = multiplier * totalSpacing view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: multiplier, constant: -constant).isActive = true } @@ -241,7 +263,7 @@ open class Stack: Container where T: StackModelProtocol { pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) if let percent = model.percent { - let multiplier = CGFloat(percent)/100.0 + let multiplier = CGFloat(percent) / 100.0 let constant = multiplier * totalSpacing view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: multiplier, constant: -constant).isActive = true } diff --git a/MVMCoreUI/Organisms/StackModel.swift b/MVMCoreUI/Organisms/StackModel.swift index 741946c5..b762a03c 100644 --- a/MVMCoreUI/Organisms/StackModel.swift +++ b/MVMCoreUI/Organisms/StackModel.swift @@ -16,8 +16,9 @@ import Foundation public var spacing: CGFloat = 16.0 public var useStackSpacingBeforeFirstItem = false - public init(molecules: [StackItemModel]) { + public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis = .vertical) { self.molecules = molecules + self.axis = axis } private enum CodingKeys: String, CodingKey { @@ -45,5 +46,6 @@ import Foundation try container.encodeIfPresent(molecules, forKey: .molecules) try container.encodeIfPresent(axis.rawValueString, forKey: .axis) try container.encodeIfPresent(spacing, forKey: .spacing) + try container.encode(moleculeName, forKey: .moleculeName) } } diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 48ca49ee..30efb2f7 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -55,7 +55,8 @@ 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) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) + // Vertical Combination Molecules @@ -64,6 +65,7 @@ import Foundation 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) @@ -73,6 +75,8 @@ import Foundation 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) // List items MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: MoleculeListItemModel.self) @@ -86,7 +90,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeCollectionViewCell.self, viewModelClass: CarouselItemModel.self) // Other Container Molecules - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeaderView.self, viewModelClass: HeaderModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeHeaderView.self, viewModelClass: MoleculeHeaderModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ModuleMolecule.self, viewModelClass: ModuleMoleculeModel.self) diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json new file mode 100644 index 00000000..b4c381b8 --- /dev/null +++ b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "paypal_horiz_logo.jpeg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "paypal_horiz_logo@2x.jpeg", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "paypal_horiz_logo@3x.jpeg", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo.jpeg b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo.jpeg new file mode 100644 index 00000000..95113ebf Binary files /dev/null and b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo.jpeg differ diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@2x.jpeg b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@2x.jpeg new file mode 100644 index 00000000..5f733990 Binary files /dev/null and b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@2x.jpeg differ diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@3x.jpeg b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@3x.jpeg new file mode 100644 index 00000000..cbd78652 Binary files /dev/null and b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@3x.jpeg differ diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 01d0a5e6..9741f110 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -23,8 +23,12 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - Computed Properties //-------------------------------------------------- - @objc public override func parsePageJSON() throws { - try parseTemplateJSON() + open override func parsePageJSON(_ error: NSErrorPointer) { + do { + try parseTemplateJSON() + } catch let parseError { + error?.pointee = parseError as NSError + } } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 03d21c6b..ef7a470d 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -12,8 +12,12 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { var observer: NSKeyValueObservation? public var templateModel: StackPageTemplateModel? - public override func parsePageJSON() throws { - try parseTemplateJSON() + open override func parsePageJSON(_ error: NSErrorPointer) { + do { + try parseTemplateJSON() + } catch let parseError { + error?.pointee = parseError as NSError + } } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Templates/ThreeLayerTemplate.swift index 785d1055..eb822279 100644 --- a/MVMCoreUI/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Templates/ThreeLayerTemplate.swift @@ -11,8 +11,13 @@ import UIKit @objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol { public var templateModel: ThreeLayerPageTemplateModel? - @objc public override func parsePageJSON() throws { - try parseTemplateJSON() + + open override func parsePageJSON(_ error: NSErrorPointer) { + do { + try parseTemplateJSON() + } catch let parseError { + error?.pointee = parseError as NSError + } } override open func viewDidLoad() {