merging
This commit is contained in:
commit
e53cc6e57c
@ -61,7 +61,6 @@
|
||||
01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */; };
|
||||
01EB368F23609801006832FA /* LabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368823609801006832FA /* LabelModel.swift */; };
|
||||
01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368923609801006832FA /* MoleculeListItemModel.swift */; };
|
||||
01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368B23609801006832FA /* MoleculeStackModel.swift */; };
|
||||
01EB369323609801006832FA /* HeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368C23609801006832FA /* HeaderModel.swift */; };
|
||||
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368D23609801006832FA /* HeadlineBodyModel.swift */; };
|
||||
01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */; };
|
||||
@ -145,6 +144,8 @@
|
||||
8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; };
|
||||
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */; };
|
||||
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */; };
|
||||
8D8067D12444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */; };
|
||||
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */; };
|
||||
8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */; };
|
||||
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */; };
|
||||
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */; };
|
||||
@ -154,9 +155,9 @@
|
||||
942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */; };
|
||||
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.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 */; };
|
||||
943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; };
|
||||
943784F5236B77BB006A1E82 /* Wheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* Wheel.swift */; };
|
||||
943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */; };
|
||||
943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; };
|
||||
94382086243238D100B43AF3 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94382085243238D100B43AF3 /* WebViewModel.swift */; };
|
||||
9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; };
|
||||
9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */; };
|
||||
@ -196,14 +197,22 @@
|
||||
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; };
|
||||
AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; };
|
||||
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; };
|
||||
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */; };
|
||||
AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */; };
|
||||
AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; };
|
||||
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; };
|
||||
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; };
|
||||
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; };
|
||||
AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatch.swift */; };
|
||||
AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; };
|
||||
BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; };
|
||||
BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; };
|
||||
BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; };
|
||||
BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */; };
|
||||
BB54C5202434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */; };
|
||||
BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */; };
|
||||
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */; };
|
||||
BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */; };
|
||||
BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */; };
|
||||
BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */; };
|
||||
BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */; };
|
||||
@ -228,9 +237,11 @@
|
||||
C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; };
|
||||
D202AFE4242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */; };
|
||||
D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */; };
|
||||
D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092348244A51D40044AD09 /* RadioSwatchModel.swift */; };
|
||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
|
||||
D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; };
|
||||
D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; };
|
||||
D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */; };
|
||||
D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */; };
|
||||
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */; };
|
||||
D21B7F75243BAC8900051ABF /* CarouselItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F74243BAC8900051ABF /* CarouselItem.swift */; };
|
||||
@ -291,7 +302,7 @@
|
||||
D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */; };
|
||||
D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837E23CCA96400DFE4FC /* TabsModel.swift */; };
|
||||
D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */; };
|
||||
D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */; };
|
||||
D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838223CCBD3F00DFE4FC /* WheelModel.swift */; };
|
||||
D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */; };
|
||||
D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838823CCCFCB00DFE4FC /* LinkModel.swift */; };
|
||||
D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */; };
|
||||
@ -399,7 +410,6 @@
|
||||
D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */; };
|
||||
D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */; };
|
||||
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */; };
|
||||
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 /* MoleculeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* MoleculeHeaderView.swift */; };
|
||||
@ -503,7 +513,6 @@
|
||||
01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = "<group>"; };
|
||||
01EB368923609801006832FA /* MoleculeListItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeListItemModel.swift; sourceTree = "<group>"; };
|
||||
01EB368A23609801006832FA /* MoleculeStackItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackItemModel.swift; sourceTree = "<group>"; };
|
||||
01EB368B23609801006832FA /* MoleculeStackModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackModel.swift; sourceTree = "<group>"; };
|
||||
01EB368C23609801006832FA /* HeaderModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderModel.swift; sourceTree = "<group>"; };
|
||||
01EB368D23609801006832FA /* HeadlineBodyModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyModel.swift; sourceTree = "<group>"; };
|
||||
01F2A03123A4498200D954D8 /* CaretLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaretLinkModel.swift; sourceTree = "<group>"; };
|
||||
@ -579,6 +588,8 @@
|
||||
8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItemModel.swift; sourceTree = "<group>"; };
|
||||
8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItem.swift; sourceTree = "<group>"; };
|
||||
8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||
8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalDataModel.swift; sourceTree = "<group>"; };
|
||||
8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalData.swift; sourceTree = "<group>"; };
|
||||
8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = "<group>"; };
|
||||
@ -589,8 +600,8 @@
|
||||
942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalMoleculeListTemplate.swift; sourceTree = "<group>"; };
|
||||
942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalMoleculeStackTemplate.swift; sourceTree = "<group>"; };
|
||||
9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = "<group>"; };
|
||||
943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = "<group>"; };
|
||||
943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = "<group>"; };
|
||||
943784F3236B77BB006A1E82 /* Wheel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Wheel.swift; sourceTree = "<group>"; };
|
||||
943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WheelAnimationHandler.swift; sourceTree = "<group>"; };
|
||||
943820832432382400B43AF3 /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = "<group>"; };
|
||||
94382085243238D100B43AF3 /* WebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewModel.swift; sourceTree = "<group>"; };
|
||||
9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBarModel.swift; sourceTree = "<group>"; };
|
||||
@ -629,14 +640,22 @@
|
||||
AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = "<group>"; };
|
||||
AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = "<group>"; };
|
||||
AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = "<group>"; };
|
||||
AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyText.swift; sourceTree = "<group>"; };
|
||||
AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyTextModel.swift; sourceTree = "<group>"; };
|
||||
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = "<group>"; };
|
||||
AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = "<group>"; };
|
||||
AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = "<group>"; };
|
||||
AAB9C109243496DD00151545 /* RadioSwatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatch.swift; sourceTree = "<group>"; };
|
||||
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = "<group>"; };
|
||||
BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||
BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = "<group>"; };
|
||||
BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsection.swift; sourceTree = "<group>"; };
|
||||
BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||
BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeBodyText.swift; sourceTree = "<group>"; };
|
||||
BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeBodyTextModel.swift; sourceTree = "<group>"; };
|
||||
BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTallModel.swift; sourceTree = "<group>"; };
|
||||
BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTall.swift; sourceTree = "<group>"; };
|
||||
BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerShort.swift; sourceTree = "<group>"; };
|
||||
@ -661,9 +680,11 @@
|
||||
C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = "<group>"; };
|
||||
D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextAlignment+Extension.swift"; sourceTree = "<group>"; };
|
||||
D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionViewScrollPosition+Extension.swift"; sourceTree = "<group>"; };
|
||||
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchModel.swift; sourceTree = "<group>"; };
|
||||
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = "<group>"; };
|
||||
D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = "<group>"; };
|
||||
D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
||||
D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = "<group>"; };
|
||||
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemModelProtocol.swift; sourceTree = "<group>"; };
|
||||
D21B7F74243BAC8900051ABF /* CarouselItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItem.swift; sourceTree = "<group>"; };
|
||||
@ -723,7 +744,7 @@
|
||||
D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsListItemModel.swift; sourceTree = "<group>"; };
|
||||
D28A837E23CCA96400DFE4FC /* TabsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsModel.swift; sourceTree = "<group>"; };
|
||||
D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionListItemModel.swift; sourceTree = "<group>"; };
|
||||
D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleProgressModel.swift; sourceTree = "<group>"; };
|
||||
D28A838223CCBD3F00DFE4FC /* WheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WheelModel.swift; sourceTree = "<group>"; };
|
||||
D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollerModel.swift; sourceTree = "<group>"; };
|
||||
D28A838823CCCFCB00DFE4FC /* LinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkModel.swift; sourceTree = "<group>"; };
|
||||
D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModel.swift; sourceTree = "<group>"; };
|
||||
@ -846,7 +867,6 @@
|
||||
D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeView.swift; sourceTree = "<group>"; };
|
||||
D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeModel.swift; sourceTree = "<group>"; };
|
||||
D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerHelper.swift; sourceTree = "<group>"; };
|
||||
D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = "<group>"; };
|
||||
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackTemplate.swift; sourceTree = "<group>"; };
|
||||
D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackCenteredTemplate.swift; sourceTree = "<group>"; };
|
||||
D2A514662213885800345BFB /* MoleculeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderView.swift; sourceTree = "<group>"; };
|
||||
@ -1112,6 +1132,10 @@
|
||||
AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */,
|
||||
8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */,
|
||||
8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */,
|
||||
BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */,
|
||||
BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */,
|
||||
8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */,
|
||||
8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */,
|
||||
C7F8012223E846C300396FBD /* ListRVWheelModel.swift */,
|
||||
C7F8012023E8303200396FBD /* ListRVWheel.swift */,
|
||||
);
|
||||
@ -1300,8 +1324,7 @@
|
||||
D260105A23D0BB7100764D80 /* StackModelProtocol.swift */,
|
||||
D260106423D0CEA700764D80 /* StackModel.swift */,
|
||||
D260105C23D0BCD400764D80 /* Stack.swift */,
|
||||
01EB368B23609801006832FA /* MoleculeStackModel.swift */,
|
||||
D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */,
|
||||
D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */,
|
||||
012A88AE238C626E00FE3DA1 /* CarouselModel.swift */,
|
||||
D2A6390022CBB1820052ED1F /* Carousel.swift */,
|
||||
);
|
||||
@ -1362,6 +1385,8 @@
|
||||
children = (
|
||||
52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */,
|
||||
52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */,
|
||||
AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */,
|
||||
AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */,
|
||||
522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */,
|
||||
522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */,
|
||||
8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */,
|
||||
@ -1448,6 +1473,11 @@
|
||||
01004F2F22721C3800991ECC /* RadioButton.swift */,
|
||||
31BE15CA23D8924C00452370 /* CheckboxModel.swift */,
|
||||
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */,
|
||||
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */,
|
||||
AAB9C10724346F4B00151545 /* RadioSwatches.swift */,
|
||||
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */,
|
||||
AAB9C109243496DD00151545 /* RadioSwatch.swift */,
|
||||
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */,
|
||||
);
|
||||
path = Selectors;
|
||||
sourceTree = "<group>";
|
||||
@ -1695,9 +1725,9 @@
|
||||
94C2D9822386F3E30006CF46 /* Label */,
|
||||
31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */,
|
||||
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */,
|
||||
D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */,
|
||||
943784F3236B77BB006A1E82 /* GraphView.swift */,
|
||||
943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */,
|
||||
D28A838223CCBD3F00DFE4FC /* WheelModel.swift */,
|
||||
943784F3236B77BB006A1E82 /* Wheel.swift */,
|
||||
943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */,
|
||||
D260105223CEA61600764D80 /* ToggleModel.swift */,
|
||||
0AA33B392398524F0067DD0F /* Toggle.swift */,
|
||||
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */,
|
||||
@ -2060,10 +2090,11 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */,
|
||||
5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */,
|
||||
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */,
|
||||
8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */,
|
||||
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */,
|
||||
943784F5236B77BB006A1E82 /* Wheel.swift in Sources */,
|
||||
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */,
|
||||
8D3BA9BF2433789900D341BA /* ListThreeColumnInternationalDataDivider.swift in Sources */,
|
||||
94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */,
|
||||
@ -2076,6 +2107,7 @@
|
||||
D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */,
|
||||
D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */,
|
||||
AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */,
|
||||
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */,
|
||||
94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */,
|
||||
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
|
||||
D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */,
|
||||
@ -2089,6 +2121,7 @@
|
||||
94382086243238D100B43AF3 /* WebViewModel.swift in Sources */,
|
||||
D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */,
|
||||
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */,
|
||||
D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */,
|
||||
0A6682A42434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift in Sources */,
|
||||
D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */,
|
||||
0A9D09202433796500D2E6C0 /* BarsIndicatorView.swift in Sources */,
|
||||
@ -2106,6 +2139,7 @@
|
||||
942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */,
|
||||
BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */,
|
||||
012A88C8238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift in Sources */,
|
||||
8D8067D12444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift in Sources */,
|
||||
0A7EF86123D8AC2500B2AAD1 /* DigitEntryFieldModel.swift in Sources */,
|
||||
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */,
|
||||
D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */,
|
||||
@ -2121,6 +2155,7 @@
|
||||
012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */,
|
||||
BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */,
|
||||
D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */,
|
||||
AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */,
|
||||
D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */,
|
||||
011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */,
|
||||
D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */,
|
||||
@ -2143,7 +2178,6 @@
|
||||
D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */,
|
||||
D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */,
|
||||
D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */,
|
||||
D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */,
|
||||
C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */,
|
||||
D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */,
|
||||
C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */,
|
||||
@ -2171,7 +2205,6 @@
|
||||
0A21DB85235E06EF00C160A2 /* MFTextField.m in Sources */,
|
||||
014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */,
|
||||
AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */,
|
||||
01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */,
|
||||
011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */,
|
||||
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */,
|
||||
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
|
||||
@ -2181,12 +2214,14 @@
|
||||
525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */,
|
||||
D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */,
|
||||
012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */,
|
||||
BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */,
|
||||
D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */,
|
||||
D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */,
|
||||
01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */,
|
||||
0A9D09212433796500D2E6C0 /* CarouselIndicatorModel.swift in Sources */,
|
||||
D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */,
|
||||
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */,
|
||||
D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */,
|
||||
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */,
|
||||
0A9D091D2433796500D2E6C0 /* BarsCarouselIndicatorModel.swift in Sources */,
|
||||
DBEFFA04225A829700230692 /* Label.swift in Sources */,
|
||||
@ -2210,6 +2245,7 @@
|
||||
0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */,
|
||||
D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */,
|
||||
BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */,
|
||||
AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */,
|
||||
D2B18B812360945C00A9AEDC /* View.swift in Sources */,
|
||||
C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */,
|
||||
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
|
||||
@ -2229,12 +2265,14 @@
|
||||
D260105D23D0BCD400764D80 /* Stack.swift in Sources */,
|
||||
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */,
|
||||
BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */,
|
||||
D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */,
|
||||
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */,
|
||||
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
|
||||
01EB368F23609801006832FA /* LabelModel.swift in Sources */,
|
||||
0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */,
|
||||
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */,
|
||||
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */,
|
||||
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */,
|
||||
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */,
|
||||
01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */,
|
||||
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */,
|
||||
@ -2242,6 +2280,7 @@
|
||||
D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */,
|
||||
D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */,
|
||||
0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */,
|
||||
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */,
|
||||
017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */,
|
||||
D29DF18121E69E50003B2FB9 /* MFView.m in Sources */,
|
||||
D28A837923C7D5BC00DFE4FC /* PageModelProtocol.swift in Sources */,
|
||||
@ -2265,6 +2304,7 @@
|
||||
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
|
||||
011D958524042432000E3791 /* RulesProtocol.swift in Sources */,
|
||||
94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */,
|
||||
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
|
||||
D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */,
|
||||
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
|
||||
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
|
||||
@ -2344,11 +2384,12 @@
|
||||
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
|
||||
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */,
|
||||
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
|
||||
AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */,
|
||||
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */,
|
||||
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
|
||||
0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */,
|
||||
94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */,
|
||||
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */,
|
||||
943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */,
|
||||
011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */,
|
||||
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
|
||||
011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */,
|
||||
|
||||
@ -13,5 +13,4 @@ import UIKit
|
||||
public var actionType: String
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
public var title: String?
|
||||
}
|
||||
|
||||
@ -22,8 +22,6 @@ public class ActionOpenPanelModel: ActionModelProtocol {
|
||||
public var panel: Panel
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
// Temporary fix till server changes
|
||||
public var title: String?
|
||||
|
||||
public init(panel: Panel) {
|
||||
self.panel = panel
|
||||
|
||||
@ -14,8 +14,6 @@ import Foundation
|
||||
public var pageType: String
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
// Temporary fix till server changes
|
||||
public var title: String?
|
||||
|
||||
public init(pageType: String) {
|
||||
self.pageType = pageType
|
||||
|
||||
@ -32,7 +32,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
|
||||
public var disabledFillColor: Color?
|
||||
public var disabledTextColor: Color?
|
||||
public var disabledBorderColor: Color?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var groupName: String = ""
|
||||
|
||||
public func setValidity(_ valid: Bool, group: FormGroupRule) {
|
||||
enabled = valid
|
||||
|
||||
@ -25,7 +25,7 @@ open class ExternalLink: Link {
|
||||
|
||||
guard let model = model as? ExternalLinkModel else { return }
|
||||
|
||||
exportImageView?.tintColor = model.textColor.uiColor
|
||||
exportImageView?.tintColor = model.enabledColor.uiColor
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -52,7 +52,7 @@ import UIKit
|
||||
guard let model = model as? LinkModel else { return }
|
||||
|
||||
setTitle(model.title, for: .normal)
|
||||
setTitleColor(model.textColor.uiColor, for: .normal)
|
||||
setTitleColor(model.enabledColor.uiColor, for: .normal)
|
||||
setTitleColor(model.disabledColor.uiColor, for: .disabled)
|
||||
isEnabled = model.enabled
|
||||
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
|
||||
|
||||
@ -21,7 +21,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
public var title: String
|
||||
public var action: ActionModelProtocol
|
||||
public var enabled = true
|
||||
public var textColor = Color(uiColor: .mvmBlack)
|
||||
public var enabledColor = Color(uiColor: .mvmBlack)
|
||||
public var disabledColor = Color(uiColor: .mvmCoolGray6)
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -43,7 +43,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
case title
|
||||
case action
|
||||
case enabled
|
||||
case textColor
|
||||
case enabledColor
|
||||
case disabledColor
|
||||
}
|
||||
|
||||
@ -60,8 +60,8 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) {
|
||||
textColor = color
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor) {
|
||||
enabledColor = color
|
||||
}
|
||||
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor) {
|
||||
@ -76,7 +76,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(textColor, forKey: .textColor)
|
||||
try container.encode(enabledColor, forKey: .enabledColor)
|
||||
try container.encode(disabledColor, forKey: .disabledColor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ open class RadioBox: Control {
|
||||
super.setupView()
|
||||
|
||||
layer.delegate = self
|
||||
layer.borderColor = UIColor.black.cgColor
|
||||
layer.borderColor = UIColor.mvmCoolGray6.cgColor
|
||||
layer.borderWidth = 1
|
||||
|
||||
label.numberOfLines = 1
|
||||
@ -60,7 +60,7 @@ open class RadioBox: Control {
|
||||
|
||||
// MARK: - MoleculeViewProtocol
|
||||
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? RadioBoxModel else { return }
|
||||
isSelected = model.selected
|
||||
@ -69,6 +69,15 @@ open class RadioBox: Control {
|
||||
subTextLabel.text = model.subText
|
||||
isOutOfStock = model.strikethrough
|
||||
subTextLabelHeightConstraint?.isActive = (subTextLabel.text?.count ?? 0) == 0
|
||||
if let color = model.selectedAccentColor?.uiColor {
|
||||
accentColor = color
|
||||
}
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
backgroundColor = .white
|
||||
accentColor = .mvmRed
|
||||
}
|
||||
|
||||
// MARK: - State Handling
|
||||
@ -77,11 +86,12 @@ open class RadioBox: Control {
|
||||
// Draw the strikethrough
|
||||
strikeLayer?.removeFromSuperlayer()
|
||||
if isOutOfStock {
|
||||
let line = getStrikeThrough(color: .black, thickness: 1)
|
||||
let line = getStrikeThrough(color: isSelected ? .black : .mvmCoolGray6, thickness: 1)
|
||||
layer.addSublayer(line)
|
||||
strikeLayer = line
|
||||
}
|
||||
|
||||
|
||||
// Draw the border
|
||||
borderLayer?.removeFromSuperlayer()
|
||||
if isSelected {
|
||||
@ -98,6 +108,7 @@ open class RadioBox: Control {
|
||||
if !isEnabled {
|
||||
let mask = getMaskLayer()
|
||||
layer.mask = mask
|
||||
maskLayer = mask
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,6 +119,7 @@ open class RadioBox: Control {
|
||||
}
|
||||
|
||||
@objc open func selectBox() {
|
||||
guard isEnabled else { return }
|
||||
isSelected = true
|
||||
radioBoxModel?.selected = isSelected
|
||||
layer.setNeedsDisplay()
|
||||
@ -131,7 +143,7 @@ open class RadioBox: Control {
|
||||
|
||||
let topLineLayer = CAShapeLayer()
|
||||
topLineLayer.fillColor = nil
|
||||
topLineLayer.strokeColor = UIColor.mvmRed.cgColor
|
||||
topLineLayer.strokeColor = accentColor.cgColor
|
||||
topLineLayer.lineWidth = 4
|
||||
topLineLayer.path = topLinePath.cgPath
|
||||
layer.addSublayer(topLineLayer)
|
||||
|
||||
@ -8,7 +8,12 @@
|
||||
|
||||
import Foundation
|
||||
open class RadioBoxCollectionViewCell: CollectionViewCell {
|
||||
let radioBox = RadioBox()
|
||||
public let radioBox = RadioBox()
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
backgroundColor = .clear
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
@ -11,8 +11,8 @@ import Foundation
|
||||
public static var identifier: String = "radioBox"
|
||||
public var text: String
|
||||
public var subText: String?
|
||||
public var backgroundColor: Color? = Color(uiColor: .white)
|
||||
public var selectedAccentColor = Color(uiColor: .mvmRed)
|
||||
public var backgroundColor: Color?
|
||||
public var selectedAccentColor: Color?
|
||||
public var selected: Bool = false
|
||||
public var enabled: Bool = true
|
||||
public var strikethrough: Bool = false
|
||||
@ -34,12 +34,8 @@ import Foundation
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
text = try typeContainer.decode(String.self, forKey: .text)
|
||||
subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText)
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) {
|
||||
selectedAccentColor = color
|
||||
}
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
|
||||
backgroundColor = color
|
||||
}
|
||||
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
|
||||
selected = isSelected
|
||||
}
|
||||
@ -58,7 +54,7 @@ import Foundation
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(text, forKey: .text)
|
||||
try container.encodeIfPresent(subText, forKey: .subText)
|
||||
try container.encode(selectedAccentColor, forKey: .selectedAccentColor)
|
||||
try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(selected, forKey: .selected)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
|
||||
@ -15,7 +15,11 @@ open class RadioBoxes: View {
|
||||
private let boxWidth: CGFloat = 151.0
|
||||
private let boxHeight: CGFloat = 64.0
|
||||
private let itemSpacing: CGFloat = 8.0
|
||||
|
||||
private var numberOfColumns: CGFloat = 2.0
|
||||
private var radioBoxesModel: RadioBoxesModel? {
|
||||
return model as? RadioBoxesModel
|
||||
}
|
||||
|
||||
private var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
/// The models for the molecules.
|
||||
@ -42,7 +46,7 @@ open class RadioBoxes: View {
|
||||
}
|
||||
|
||||
// MARK: - MoleculeViewProtocol
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
self.delegateObject = delegateObject
|
||||
|
||||
@ -94,7 +98,7 @@ open class RadioBoxes: View {
|
||||
}
|
||||
|
||||
// Calculate the height
|
||||
let rows = ceil(CGFloat(boxes.count) / 2.0)
|
||||
let rows = ceil(CGFloat(boxes.count) / numberOfColumns)
|
||||
let height = (rows * boxHeight) + ((rows - 1) * itemSpacing)
|
||||
collectionViewHeight?.constant = height
|
||||
}
|
||||
@ -102,7 +106,7 @@ open class RadioBoxes: View {
|
||||
|
||||
extension RadioBoxes: UICollectionViewDelegateFlowLayout {
|
||||
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||
let itemWidth: CGFloat = (collectionView.bounds.width - itemSpacing) / 2
|
||||
let itemWidth: CGFloat = (collectionView.bounds.width - itemSpacing) / numberOfColumns
|
||||
return CGSize(width: itemWidth, height: boxHeight)
|
||||
}
|
||||
}
|
||||
@ -117,7 +121,16 @@ extension RadioBoxes: UICollectionViewDataSource {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioBoxCollectionViewCell", for: indexPath) as? RadioBoxCollectionViewCell else {
|
||||
fatalError()
|
||||
}
|
||||
cell.reset()
|
||||
cell.radioBox.isUserInteractionEnabled = false
|
||||
|
||||
if let color = radioBoxesModel?.boxesColor {
|
||||
cell.radioBox.backgroundColor = color.uiColor
|
||||
}
|
||||
if let color = radioBoxesModel?.selectedAccentColor {
|
||||
cell.radioBox.accentColor = color.uiColor
|
||||
}
|
||||
|
||||
cell.set(with: molecule, delegateObject, nil)
|
||||
cell.updateView(size ?? collectionView.bounds.width)
|
||||
if molecule.selected {
|
||||
@ -129,13 +142,18 @@ extension RadioBoxes: UICollectionViewDataSource {
|
||||
}
|
||||
|
||||
extension RadioBoxes: UICollectionViewDelegate {
|
||||
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
||||
guard let molecule = boxes?[indexPath.row] else { return false }
|
||||
return molecule.enabled
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return }
|
||||
cell.radioBox.selectBox()
|
||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
}
|
||||
|
||||
public func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
||||
open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return }
|
||||
cell.radioBox.deselectBox()
|
||||
}
|
||||
|
||||
@ -9,9 +9,10 @@
|
||||
import Foundation
|
||||
@objcMembers public class RadioBoxesModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
public static var identifier: String = "radioBoxes"
|
||||
public var boxes: [RadioBoxModel]
|
||||
public var backgroundColor: Color?
|
||||
public var selectedAccentColor: Color?
|
||||
public var boxes: [RadioBoxModel]
|
||||
public var boxesColor: Color?
|
||||
public var fieldKey: String?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
@ -28,6 +29,7 @@ import Foundation
|
||||
case moleculeName
|
||||
case selectedAccentColor
|
||||
case backgroundColor
|
||||
case boxesColor
|
||||
case boxes
|
||||
case fieldKey
|
||||
case groupName
|
||||
@ -37,6 +39,7 @@ import Foundation
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
boxesColor = try typeContainer.decodeIfPresent(Color.self, forKey: .boxesColor)
|
||||
boxes = try typeContainer.decode([RadioBoxModel].self, forKey: .boxes)
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
|
||||
@ -90,6 +90,9 @@ import UIKit
|
||||
|
||||
/// The action performed when tapped.
|
||||
func tapAction() {
|
||||
if !isEnabled {
|
||||
return
|
||||
}
|
||||
if let radioButtonModel = radioButtonSelectionHelper {
|
||||
radioButtonModel.selected(self)
|
||||
} else {
|
||||
|
||||
166
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift
Normal file
166
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift
Normal file
@ -0,0 +1,166 @@
|
||||
//
|
||||
// RadioSwatch.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 01/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
open class RadioSwatch: Control {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public let bottomText = Label.createLabelRegularMicro(true)
|
||||
|
||||
private var circleLayer: CAShapeLayer?
|
||||
private var selectedLayer: CALayer?
|
||||
private var strikeLayer: CALayer?
|
||||
private var maskLayer: CALayer?
|
||||
|
||||
public var radioSwatchModel: RadioSwatchModel? {
|
||||
return model as? RadioSwatchModel
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
//--------------------------------------------------
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
bottomText.updateView(size)
|
||||
layer.setNeedsDisplay()
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
addSubview(bottomText)
|
||||
bottomText.textAlignment = .center
|
||||
NSLayoutConstraint.constraintPinSubview(bottomText, pinTop: true, topConstant: 38, pinBottom: true, bottomConstant: 0, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0)
|
||||
addTarget(self, action: #selector(selectSwatch), for: .touchUpInside)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? RadioSwatchModel else { return }
|
||||
isSelected = model.selected
|
||||
isEnabled = model.enabled
|
||||
bottomText.text = model.text
|
||||
}
|
||||
|
||||
public override func reset() {
|
||||
super.reset()
|
||||
isSelected = false
|
||||
isEnabled = true
|
||||
bottomText.text = nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - State Handling
|
||||
//------------------------------------------------------
|
||||
open override func draw(_ layer: CALayer, in ctx: CGContext) {
|
||||
//Draw the swatch
|
||||
circleLayer?.removeFromSuperlayer()
|
||||
let circle = getCircle(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1)
|
||||
layer.addSublayer(circle)
|
||||
circleLayer = circle
|
||||
|
||||
//Draw the strikethrough
|
||||
strikeLayer?.removeFromSuperlayer()
|
||||
if radioSwatchModel?.strikethrough ?? false {
|
||||
let line = getStrikeThrough(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1)
|
||||
layer.addSublayer(line)
|
||||
strikeLayer = line
|
||||
}
|
||||
|
||||
//Draw the selected layer
|
||||
selectedLayer?.removeFromSuperlayer()
|
||||
if isSelected {
|
||||
let outerCircle = getSelectedLayer(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1)
|
||||
layer.addSublayer(outerCircle)
|
||||
selectedLayer = outerCircle
|
||||
bottomText.isHidden = false
|
||||
} else {
|
||||
bottomText.isHidden = true
|
||||
}
|
||||
|
||||
//Handle Mask
|
||||
maskLayer?.removeFromSuperlayer()
|
||||
if !isEnabled {
|
||||
let mask = getMaskLayer()
|
||||
layer.mask = mask
|
||||
maskLayer = mask
|
||||
}
|
||||
}
|
||||
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
// Accounts for any size changes
|
||||
layer.setNeedsDisplay()
|
||||
}
|
||||
|
||||
@objc open func selectSwatch() {
|
||||
guard isEnabled else { return }
|
||||
isSelected = true
|
||||
radioSwatchModel?.selected = isSelected
|
||||
layer.setNeedsDisplay()
|
||||
}
|
||||
|
||||
@objc open func deselectSwatch() {
|
||||
isSelected = false
|
||||
radioSwatchModel?.selected = isSelected
|
||||
layer.setNeedsDisplay()
|
||||
}
|
||||
|
||||
func getCircle(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
|
||||
let circle = CAShapeLayer()
|
||||
circle.name = "innercircle"
|
||||
circle.fillColor = radioSwatchModel?.color.cgColor ?? UIColor.blue.cgColor
|
||||
circle.opacity = 1.0
|
||||
circle.lineWidth = thickness
|
||||
circle.strokeColor = color.cgColor
|
||||
|
||||
let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30))
|
||||
circle.path = circlePath.cgPath
|
||||
return circle
|
||||
}
|
||||
|
||||
func getStrikeThrough(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
|
||||
let strikeThrough = CAShapeLayer()
|
||||
strikeThrough.name = "strikethrough"
|
||||
strikeThrough.fillColor = nil
|
||||
strikeThrough.opacity = 1.0
|
||||
strikeThrough.lineWidth = thickness
|
||||
strikeThrough.strokeColor = color.cgColor
|
||||
|
||||
let linePath = UIBezierPath()
|
||||
linePath.move(to: CGPoint(x: 12, y: 31))
|
||||
linePath.addLine(to: CGPoint(x: 42, y: 1))
|
||||
strikeThrough.path = linePath.cgPath
|
||||
return strikeThrough
|
||||
}
|
||||
|
||||
func getSelectedLayer(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
|
||||
circleLayer?.path = UIBezierPath(ovalIn: CGRect(x: 15, y: 4, width: 24, height: 24)).cgPath
|
||||
let circle = CAShapeLayer()
|
||||
circle.name = "outercircle"
|
||||
circle.fillColor = UIColor.clear.cgColor
|
||||
circle.opacity = 1.0
|
||||
circle.lineWidth = thickness
|
||||
circle.strokeColor = color.cgColor
|
||||
|
||||
let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30))
|
||||
circle.path = circlePath.cgPath
|
||||
return circle
|
||||
}
|
||||
|
||||
func getMaskLayer() -> CALayer {
|
||||
let mask = CALayer()
|
||||
mask.backgroundColor = UIColor.white.cgColor
|
||||
mask.opacity = 0.3
|
||||
mask.frame = bounds
|
||||
return mask
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
//
|
||||
// RadioSwatchCollectionViewCell.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 13/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
open class RadioSwatchCollectionViewCell: CollectionViewCell {
|
||||
public let radioSwatch = RadioSwatch()
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(radioSwatch)
|
||||
MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let model = model as? RadioSwatchModel else { return }
|
||||
radioSwatch.set(with: model, delegateObject, additionalData)
|
||||
}
|
||||
}
|
||||
64
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift
Normal file
64
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift
Normal file
@ -0,0 +1,64 @@
|
||||
//
|
||||
// RadioSwatchModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/17/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class RadioSwatchModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "radioSwatch"
|
||||
public var backgroundColor: Color?
|
||||
public var color: Color = Color(uiColor: .mvmBlue)
|
||||
public var text: String?
|
||||
public var selected: Bool = false
|
||||
public var enabled: Bool = true
|
||||
public var strikethrough: Bool = false
|
||||
public var fieldValue: String?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case color
|
||||
case text
|
||||
case selected
|
||||
case enabled
|
||||
case strikethrough
|
||||
case fieldValue
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) {
|
||||
self.color = color
|
||||
}
|
||||
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
|
||||
if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
|
||||
self.selected = selected
|
||||
}
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
|
||||
self.strikethrough = strikethrough
|
||||
}
|
||||
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(color, forKey: .color)
|
||||
try container.encodeIfPresent(text, forKey: .text)
|
||||
try container.encode(selected, forKey: .selected)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(strikethrough, forKey: .strikethrough)
|
||||
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
152
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift
Normal file
152
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift
Normal file
@ -0,0 +1,152 @@
|
||||
//
|
||||
// RadioSwatches.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 01/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
open class RadioSwatches: View {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public var collectionView: CollectionView!
|
||||
public var swatches: [RadioSwatchModel]?
|
||||
private var size: CGFloat?
|
||||
private var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//------------------------------------------------------
|
||||
public var collectionViewHeight: NSLayoutConstraint?
|
||||
private let cellSize: CGFloat = 54.0
|
||||
private let itemSpacing: CGFloat = 8.0
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
//--------------------------------------------------
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
// Accounts for any collection size changes
|
||||
setHeight()
|
||||
DispatchQueue.main.async {
|
||||
self.collectionView.collectionViewLayout.invalidateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
collectionView = createCollectionView()
|
||||
addSubview(collectionView)
|
||||
NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)
|
||||
collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 100)
|
||||
collectionViewHeight?.isActive = true
|
||||
}
|
||||
|
||||
@objc override open func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
self.size = size
|
||||
collectionView.updateView(size)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
self.delegateObject = delegateObject
|
||||
|
||||
guard let radioSwatchesModel = model as? RadioSwatchesModel else { return }
|
||||
swatches = radioSwatchesModel.swatches
|
||||
FormValidator.setupValidation(for: radioSwatchesModel, delegate: delegateObject?.formHolderDelegate)
|
||||
collectionView.reloadData()
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//------------------------------------------------------
|
||||
/// Creates the collection view.
|
||||
open func createCollectionView() -> CollectionView {
|
||||
let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout())
|
||||
collection.dataSource = self
|
||||
collection.delegate = self
|
||||
collection.register(RadioSwatchCollectionViewCell.self, forCellWithReuseIdentifier: "RadioSwatchCollectionViewCell")
|
||||
return collection
|
||||
}
|
||||
|
||||
/// Creates the layout for the collection.
|
||||
open func createCollectionViewLayout() -> UICollectionViewLayout {
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
layout.scrollDirection = .vertical
|
||||
layout.minimumLineSpacing = itemSpacing
|
||||
layout.minimumInteritemSpacing = itemSpacing
|
||||
return layout
|
||||
}
|
||||
|
||||
open func setHeight() {
|
||||
guard let swatches = swatches, swatches.count > 0 else {
|
||||
collectionViewHeight?.constant = 0
|
||||
return
|
||||
}
|
||||
// Calculate the height
|
||||
let swatchesInRow = floor(CGFloat(collectionView.bounds.width/(cellSize + itemSpacing)))
|
||||
let numberOfRows = ceil(CGFloat(swatches.count)/swatchesInRow)
|
||||
let height = (numberOfRows * cellSize) + (itemSpacing * (numberOfRows-1))
|
||||
|
||||
if let oldHeight = collectionViewHeight?.constant,
|
||||
height != oldHeight {
|
||||
// Notify delegate of height change, called async to avoid various race conditions caused while happening while laying out initially.
|
||||
DispatchQueue.main.async {
|
||||
self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
|
||||
}
|
||||
}
|
||||
collectionViewHeight?.constant = CGFloat(height)
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Delegate methods
|
||||
//------------------------------------------------------
|
||||
extension RadioSwatches: UICollectionViewDelegateFlowLayout {
|
||||
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||
return CGSize(width: cellSize, height: cellSize)
|
||||
}
|
||||
}
|
||||
|
||||
extension RadioSwatches: UICollectionViewDataSource {
|
||||
open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return swatches?.count ?? 0
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchCollectionViewCell", for: indexPath) as? RadioSwatchCollectionViewCell else {
|
||||
fatalError()
|
||||
}
|
||||
cell.reset()
|
||||
cell.radioSwatch.isUserInteractionEnabled = false
|
||||
cell.set(with: molecule, delegateObject, nil)
|
||||
cell.updateView(size ?? collectionView.bounds.width)
|
||||
if molecule.selected {
|
||||
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
|
||||
}
|
||||
cell.layoutIfNeeded()
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
extension RadioSwatches: UICollectionViewDelegate {
|
||||
open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
||||
guard let molecule = swatches?[indexPath.row] else { return false }
|
||||
return molecule.enabled
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return }
|
||||
cell.radioSwatch.selectSwatch()
|
||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return }
|
||||
cell.radioSwatch.deselectSwatch()
|
||||
}
|
||||
}
|
||||
54
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift
Normal file
54
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// RadioSwatchesModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 31/03/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
public static var identifier: String = "radioSwatches"
|
||||
public var backgroundColor: Color?
|
||||
public var swatches: [RadioSwatchModel]
|
||||
public var fieldKey: String?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
|
||||
/// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch.
|
||||
public func formFieldValue() -> AnyHashable? {
|
||||
let selectedSwatch = swatches.first { (swatch) -> Bool in
|
||||
return swatch.selected
|
||||
}
|
||||
return selectedSwatch?.fieldValue ?? selectedSwatch?.text
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case swatches
|
||||
case fieldKey
|
||||
case groupName
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
swatches = try typeContainer.decode([RadioSwatchModel].self, forKey: .swatches)
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
baseValue = formFieldValue()
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(swatches, forKey: .swatches)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encode(groupName, forKey: .groupName)
|
||||
}
|
||||
}
|
||||
@ -258,12 +258,12 @@ import UIKit
|
||||
title = model.title
|
||||
feedback = model.feedback
|
||||
errorMessage = model.errorMessage
|
||||
isEnabled = model.isEnabled
|
||||
isEnabled = model.enabled
|
||||
|
||||
if let isLocked = model.isLocked {
|
||||
if let isLocked = model.locked {
|
||||
self.isLocked = isLocked
|
||||
|
||||
} else if let isSelected = model.isSelected{
|
||||
} else if let isSelected = model.selected {
|
||||
self.isSelected = isSelected
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol {
|
||||
@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, EnableableModelProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
@ -23,9 +23,9 @@ import Foundation
|
||||
public var title: String?
|
||||
public var feedback: String?
|
||||
public var errorMessage: String = ""
|
||||
public var isEnabled: Bool = true
|
||||
public var isLocked: Bool?
|
||||
public var isSelected: Bool?
|
||||
public var enabled: Bool = true
|
||||
public var locked: Bool?
|
||||
public var selected: Bool?
|
||||
public var text: String?
|
||||
|
||||
public var fieldKey: String?
|
||||
@ -52,14 +52,12 @@ import Foundation
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case title = "label"
|
||||
case isEnabled
|
||||
case title
|
||||
case enabled
|
||||
case feedback
|
||||
case errorMessage = "errorMsg"
|
||||
case isLocked
|
||||
case isSelected
|
||||
case isValid
|
||||
case isRequired = "required"
|
||||
case errorMessage
|
||||
case locked
|
||||
case selected
|
||||
case text
|
||||
case fieldKey
|
||||
case groupName
|
||||
@ -84,10 +82,9 @@ import Foundation
|
||||
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
|
||||
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
|
||||
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) ?? ""
|
||||
isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true
|
||||
isLocked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isLocked)
|
||||
isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected)
|
||||
isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid)
|
||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||
locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
|
||||
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
|
||||
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
|
||||
|
||||
baseValue = text
|
||||
@ -104,12 +101,11 @@ import Foundation
|
||||
try container.encodeIfPresent(title, forKey: .title)
|
||||
try container.encodeIfPresent(feedback, forKey: .feedback)
|
||||
try container.encode(errorMessage, forKey: .errorMessage)
|
||||
try container.encode(isEnabled, forKey: .isEnabled)
|
||||
try container.encode(isLocked, forKey: .isLocked)
|
||||
try container.encode(isSelected, forKey: .isSelected)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(isValid, forKey: .isValid)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(locked, forKey: .locked)
|
||||
try container.encode(selected, forKey: .selected)
|
||||
try container.encodeIfPresent(text, forKey: .text)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,14 +314,7 @@ import UIKit
|
||||
break
|
||||
}
|
||||
|
||||
if let regex = model.regex, !regex.isEmpty {
|
||||
validationBlock = { enteredValue in
|
||||
guard let value = enteredValue else { return false }
|
||||
return MVMCoreUIUtility.validate(value, withRegularExpression: regex)
|
||||
}
|
||||
} else {
|
||||
defaultValidationBlock()
|
||||
}
|
||||
defaultValidationBlock()
|
||||
|
||||
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
|
||||
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
|
||||
|
||||
@ -27,7 +27,6 @@
|
||||
public var enabledTextColor: Color?
|
||||
public var disabledTextColor: Color?
|
||||
public var type: EntryType?
|
||||
public var regex: String?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
@ -40,7 +39,6 @@
|
||||
case enabledTextColor
|
||||
case disabledTextColor
|
||||
case type
|
||||
case regex
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -55,7 +53,6 @@
|
||||
enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor)
|
||||
disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor)
|
||||
type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type)
|
||||
regex = try typeContainer.decodeIfPresent(String.self, forKey: .regex)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
@ -67,6 +64,5 @@
|
||||
try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor)
|
||||
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor)
|
||||
try container.encodeIfPresent(type, forKey: .type)
|
||||
try container.encodeIfPresent(regex, forKey: .regex)
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,8 +14,8 @@ import Foundation
|
||||
// MARK: - Outlets
|
||||
//------------------------------------------------------
|
||||
|
||||
let leftTextLabel = Label.commonLabelB1(true)
|
||||
let rightTextLabel = Label.commonLabelB1(true)
|
||||
let leftTextLabel = Label.createLabelBoldBodySmall(true)
|
||||
let rightTextLabel = Label.createLabelBoldBodySmall(true)
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
@ -23,6 +23,29 @@ import Foundation
|
||||
|
||||
var rightTextLabelLeading: NSLayoutConstraint?
|
||||
var leftTextLabelTrailing: NSLayoutConstraint?
|
||||
var rightTextLabelTrailing: NSLayoutConstraint?
|
||||
|
||||
private func constrainLeftLabelOnly() {
|
||||
|
||||
deactivateMiddleConstraint()
|
||||
leftTextLabelTrailing?.isActive = false
|
||||
leftTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor)
|
||||
leftTextLabelTrailing?.isActive = true
|
||||
}
|
||||
|
||||
private func constrainRightLabelOnly() {
|
||||
|
||||
deactivateMiddleConstraint()
|
||||
rightTextLabelLeading?.isActive = false
|
||||
rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||
rightTextLabelLeading?.isActive = true
|
||||
}
|
||||
|
||||
private func deactivateMiddleConstraint() {
|
||||
|
||||
leftTextLabelTrailing?.isActive = false
|
||||
rightTextLabelLeading?.isActive = false
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Initialization
|
||||
@ -43,8 +66,6 @@ import Foundation
|
||||
override open func setupView() {
|
||||
super.setupView()
|
||||
|
||||
guard subviews.isEmpty else { return }
|
||||
|
||||
addSubview(leftTextLabel)
|
||||
addSubview(rightTextLabel)
|
||||
|
||||
@ -67,7 +88,7 @@ import Foundation
|
||||
// Resolves text layout issues found between both dynamically sized labels, number is not exact but performs as required.
|
||||
if leftTextLabel.hasText && rightTextLabel.hasText {
|
||||
let padding = MFStyler.defaultHorizontalPadding(forSize: size) * 2
|
||||
let maximumTextWidth = (size - (padding + 16)) * 0.4
|
||||
let maximumTextWidth = (size - (padding + Padding.Four)) * 0.4
|
||||
// Subtracting 10 resolves issues of SE and iPad
|
||||
rightTextLabel.preferredMaxLayoutWidth = round(maximumTextWidth) - 10
|
||||
} else {
|
||||
@ -84,57 +105,38 @@ import Foundation
|
||||
leftTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
|
||||
leftTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
|
||||
|
||||
let leftTextBottom = leftTextLabel.bottomAnchor.constraint(equalTo: bottomAnchor)
|
||||
let leftTextBottom = bottomAnchor.constraint(equalTo: leftTextLabel.bottomAnchor)
|
||||
leftTextBottom.priority = UILayoutPriority(249)
|
||||
leftTextBottom.isActive = true
|
||||
|
||||
bottomAnchor.constraint(greaterThanOrEqualTo: leftTextLabel.bottomAnchor).isActive = true
|
||||
|
||||
rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor, constant: 16)
|
||||
rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor, constant: Padding.Four)
|
||||
rightTextLabelLeading?.isActive = true
|
||||
|
||||
rightTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
|
||||
let rightLayout = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor)
|
||||
rightLayout.priority = UILayoutPriority(rawValue: 995)
|
||||
rightLayout.isActive = true
|
||||
|
||||
let rightTextBottom = rightTextLabel.bottomAnchor.constraint(equalTo: bottomAnchor)
|
||||
rightTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor)
|
||||
rightTextLabelTrailing?.isActive = true
|
||||
|
||||
let rightTextBottom = bottomAnchor.constraint(equalTo: rightTextLabel.bottomAnchor)
|
||||
rightTextBottom.priority = UILayoutPriority(rawValue: 249)
|
||||
rightTextBottom.isActive = true
|
||||
|
||||
bottomAnchor.constraint(greaterThanOrEqualTo: rightTextLabel.bottomAnchor).isActive = true
|
||||
|
||||
let leftTextWidth = leftTextLabel.widthAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.widthAnchor, multiplier: 0.6)
|
||||
let leftTextWidth = leftTextLabel.widthAnchor.constraint(equalTo: layoutMarginsGuide.widthAnchor, multiplier: 0.6)
|
||||
leftTextWidth.priority = UILayoutPriority(rawValue: 995)
|
||||
leftTextWidth.isActive = true
|
||||
|
||||
let rightTextWidth = rightTextLabel.widthAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.widthAnchor, multiplier: 0.4)
|
||||
rightTextWidth.priority = UILayoutPriority(rawValue: 906)
|
||||
let rightTextWidth = rightTextLabel.widthAnchor.constraint(equalTo: layoutMarginsGuide.widthAnchor, multiplier: 0.4)
|
||||
rightTextWidth.priority = UILayoutPriority(rawValue: 995)
|
||||
rightTextWidth.isActive = true
|
||||
|
||||
leftTextLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal)
|
||||
rightTextLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal)
|
||||
|
||||
leftTextLabel.setContentHuggingPriority(.required, for: .vertical)
|
||||
rightTextLabel.setContentHuggingPriority(.required, for: .vertical)
|
||||
|
||||
rightTextLabel.setContentHuggingPriority(.required, for: .horizontal)
|
||||
leftTextLabel.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
rightTextLabel.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
rightTextLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 902), for: .horizontal)
|
||||
}
|
||||
|
||||
private func constrainLeftLabel() {
|
||||
|
||||
deactivateMiddleConstraint()
|
||||
leftTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor)
|
||||
leftTextLabelTrailing?.isActive = true
|
||||
}
|
||||
|
||||
private func constrainRightLabel() {
|
||||
|
||||
deactivateMiddleConstraint()
|
||||
rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||
rightTextLabelLeading?.isActive = true
|
||||
rightTextLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
}
|
||||
|
||||
override open func reset() {
|
||||
@ -144,31 +146,31 @@ import Foundation
|
||||
constrainBothLabels()
|
||||
leftTextLabel.text = ""
|
||||
rightTextLabel.text = ""
|
||||
leftTextLabel.textAlignment = .left
|
||||
rightTextLabel.textAlignment = .right
|
||||
backgroundColor = nil
|
||||
}
|
||||
|
||||
private func deactivateMiddleConstraint() {
|
||||
|
||||
leftTextLabelTrailing?.isActive = false
|
||||
rightTextLabelLeading?.isActive = false
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Atomization
|
||||
//------------------------------------------------------
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let leftRightLabelModel = model as? LeftRightLabelModel else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let leftRightLabelModel = model as? LeftRightLabelModel else { return }
|
||||
|
||||
leftTextLabel.set(with: leftRightLabelModel.leftText, delegateObject, additionalData)
|
||||
rightTextLabel.setOptional(with: leftRightLabelModel.rightText, delegateObject, additionalData)
|
||||
|
||||
|
||||
// Label defaults to .left if no textAlignment value is provided in model.
|
||||
rightTextLabel.textAlignment = leftRightLabelModel.rightText?.textAlignment ?? .right
|
||||
|
||||
if !leftTextLabel.hasText {
|
||||
constrainRightLabel()
|
||||
constrainRightLabelOnly()
|
||||
|
||||
} else if !rightTextLabel.hasText {
|
||||
constrainLeftLabel()
|
||||
constrainLeftLabelOnly()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,39 +9,27 @@
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class MultiProgress: View {
|
||||
private let stack = Stack<StackModel>()
|
||||
var multiProgressModel: MultiProgressBarModel? {
|
||||
get { return model as? MultiProgressBarModel }
|
||||
}
|
||||
|
||||
///passing value to progressList creates corresponding progress bars
|
||||
var progressList: Array<SingleProgressBarModel>? {
|
||||
didSet {
|
||||
for subview in subviews {
|
||||
subview.removeFromSuperview()
|
||||
}
|
||||
guard (progressList?.count ?? 0) > 0 else {
|
||||
return
|
||||
}
|
||||
var previous: UIView?
|
||||
for progressObject in progressList! {
|
||||
guard progressObject.progress > 0.0 else {
|
||||
continue
|
||||
}
|
||||
let view = UIView(frame: .zero)
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(view)
|
||||
view.backgroundColor = progressObject.progressColor.uiColor
|
||||
view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.progress/100.0).isActive = true
|
||||
view.leadingAnchor.constraint(equalTo: previous?.trailingAnchor ?? leadingAnchor).isActive = true
|
||||
previous = view
|
||||
NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false)
|
||||
}
|
||||
}
|
||||
|
||||
public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.init(frame: .zero)
|
||||
set(with: model, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
var roundedRect: Bool = false {
|
||||
public required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
}
|
||||
|
||||
var roundedCorners: Bool = false {
|
||||
didSet {
|
||||
if roundedRect {
|
||||
if roundedCorners {
|
||||
layer.cornerRadius = (thicknessConstraint?.constant ?? defaultHeight)/2
|
||||
} else {
|
||||
layer.cornerRadius = 0
|
||||
@ -57,28 +45,53 @@ import UIKit
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
backgroundColor = .mfLightSilver()
|
||||
clipsToBounds = true
|
||||
|
||||
addSubview(stack)
|
||||
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
|
||||
stack.backgroundColor = backgroundColor
|
||||
stack.contentView.backgroundColor = .white
|
||||
stack.model = StackModel(molecules: [], axis: .horizontal, spacing: 2)
|
||||
stack.stackModel?.horizontalAlignment = .leading
|
||||
|
||||
if thicknessConstraint == nil {
|
||||
thicknessConstraint = heightAnchor.constraint(equalToConstant: defaultHeight)
|
||||
thicknessConstraint?.isActive = true
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the bars
|
||||
open func set(with progressList: Array<SingleProgressBarModel>, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
stack.removeAllItemViews()
|
||||
guard let stackModel = stack.stackModel else { return }
|
||||
var views: [StackItem] = []
|
||||
var models: [StackItemModel] = []
|
||||
for progressObject in progressList {
|
||||
guard progressObject.percent > 0.0 else { continue }
|
||||
let model = StackItemModel(percent: Int(progressObject.percent), horizontalAlignment: .fill, verticalAlignment: .fill)
|
||||
model.backgroundColor = progressObject.color
|
||||
models.append(model)
|
||||
views.append(StackItem())
|
||||
}
|
||||
stack.stackItems = views
|
||||
stackModel.molecules = models
|
||||
stack.set(with: stackModel, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
//MARK: - MoleculeViewProtocol
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let multiProgressModel = multiProgressModel else {
|
||||
return
|
||||
}
|
||||
roundedRect = multiProgressModel.roundedRect ?? false
|
||||
guard let multiProgressModel = multiProgressModel else { return }
|
||||
roundedCorners = multiProgressModel.roundedCorners ?? false
|
||||
thicknessConstraint?.constant = multiProgressModel.thickness ?? defaultHeight
|
||||
progressList = multiProgressModel.progressList
|
||||
|
||||
stack.model?.backgroundColor = model.backgroundColor
|
||||
set(with: multiProgressModel.progressList, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
backgroundColor = .mfLightSilver()
|
||||
progressList = nil
|
||||
stack.reset()
|
||||
set(with: [], nil, nil)
|
||||
}
|
||||
|
||||
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
|
||||
@ -9,12 +9,12 @@
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class SingleProgressBarModel: Codable {
|
||||
@Percent var progress: CGFloat
|
||||
var progressColor: Color
|
||||
@Percent var percent: CGFloat
|
||||
var color: Color
|
||||
|
||||
init(_ progress: CGFloat, color: Color) {
|
||||
self.progress = progress
|
||||
self.progressColor = color
|
||||
init(_ percent: CGFloat, color: Color) {
|
||||
self.percent = percent
|
||||
self.color = color
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,13 +23,13 @@ import Foundation
|
||||
public var progressList: [SingleProgressBarModel]
|
||||
public var backgroundColor: Color?
|
||||
public var thickness: CGFloat?
|
||||
public var roundedRect: Bool?
|
||||
public var roundedCorners: Bool?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case progressList
|
||||
case thickness
|
||||
case roundedRect
|
||||
case roundedCorners
|
||||
case backgroundColor
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ import Foundation
|
||||
progressList = try typeContainer.decode([SingleProgressBarModel].self, forKey: .progressList)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness)
|
||||
roundedRect = try typeContainer.decodeIfPresent(Bool.self, forKey: .roundedRect)
|
||||
roundedCorners = try typeContainer.decodeIfPresent(Bool.self, forKey: .roundedCorners)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -50,7 +50,7 @@ import Foundation
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(progressList, forKey: .progressList)
|
||||
try container.encodeIfPresent(thickness, forKey: .thickness)
|
||||
try container.encodeIfPresent(roundedRect, forKey: .roundedRect)
|
||||
try container.encodeIfPresent(roundedCorners, forKey: .roundedCorners)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ import Foundation
|
||||
var thickness: CGFloat = 8.0 {
|
||||
willSet(newValue) {
|
||||
heightAnchor.constraint(equalToConstant: newValue).isActive = true
|
||||
if progressBarModel?.isRounded ?? false {
|
||||
if progressBarModel?.roundedCorners ?? false {
|
||||
layer.cornerRadius = newValue/2.0
|
||||
} else {
|
||||
progressViewStyle = .bar
|
||||
@ -52,12 +52,11 @@ import Foundation
|
||||
|
||||
//MARK: - MoleculeViewProtocol
|
||||
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let progressBarModel = model as? ProgressBarModel else {
|
||||
return
|
||||
}
|
||||
guard let progressBarModel = model as? ProgressBarModel else { return }
|
||||
self.progressBarModel = progressBarModel
|
||||
thickness = progressBarModel.thickness ?? 8
|
||||
progress = Float((progressBarModel.percent)/100.0)
|
||||
progressTintColor = progressBarModel.progressColor.uiColor
|
||||
progressTintColor = progressBarModel.color.uiColor
|
||||
if let backgroundColor = progressBarModel.backgroundColor {
|
||||
trackTintColor = backgroundColor.uiColor
|
||||
}
|
||||
|
||||
@ -11,17 +11,17 @@ import Foundation
|
||||
@objcMembers public class ProgressBarModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "progressBar"
|
||||
@Percent public var percent: CGFloat
|
||||
public var progressColor: Color = Color(uiColor: .mfCerulean())
|
||||
public var color: Color = Color(uiColor: .mfCerulean())
|
||||
public var backgroundColor: Color? = Color(uiColor: .mfLightSilver())
|
||||
public var isRounded: Bool?
|
||||
public var roundedCorners: Bool?
|
||||
public var thickness: CGFloat?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case isRounded = "roundRect"
|
||||
case roundedCorners
|
||||
case thickness
|
||||
case percent
|
||||
case progressColor
|
||||
case color
|
||||
case backgroundColor
|
||||
}
|
||||
|
||||
@ -32,13 +32,13 @@ import Foundation
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
percent = try typeContainer.decode(CGFloat.self, forKey: .percent)
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .progressColor) {
|
||||
progressColor = color
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) {
|
||||
self.color = color
|
||||
}
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
|
||||
backgroundColor = color
|
||||
}
|
||||
isRounded = try typeContainer.decodeIfPresent(Bool.self, forKey: .isRounded)
|
||||
roundedCorners = try typeContainer.decodeIfPresent(Bool.self, forKey: .roundedCorners)
|
||||
thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness)
|
||||
}
|
||||
|
||||
@ -46,9 +46,9 @@ import Foundation
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(percent, forKey: .percent)
|
||||
try container.encode(progressColor, forKey: .progressColor)
|
||||
try container.encode(color, forKey: .color)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(isRounded, forKey: .isRounded)
|
||||
try container.encodeIfPresent(roundedCorners, forKey: .roundedCorners)
|
||||
try container.encodeIfPresent(thickness, forKey: .thickness)
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,13 +25,13 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
//--------------------------------------------------
|
||||
|
||||
/// Holds the on and off colors for the container.
|
||||
public var containerTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmGreen, off: .mvmBlack)
|
||||
public var containerTintColor: (on: UIColor, off: UIColor) = (on: .mvmGreen, off: .mvmBlack)
|
||||
|
||||
/// Holds the on and off colors for the knob.
|
||||
public var knobTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmWhite, off: .mvmWhite)
|
||||
public var knobTintColor: (on: UIColor, off: UIColor) = (on: .mvmWhite, off: .mvmWhite)
|
||||
|
||||
/// Holds the on and off colors for the disabled state..
|
||||
public var disabledTintColor: (container: UIColor?, knob: UIColor?)? = (container: .mvmCoolGray3, knob: .mvmWhite)
|
||||
public var disabledTintColor: (container: UIColor, knob: UIColor) = (container: .mvmCoolGray3, knob: .mvmWhite)
|
||||
|
||||
/// Set this flag to false if you do not want to animate state changes.
|
||||
public var isAnimated = true
|
||||
@ -62,8 +62,8 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
didSet {
|
||||
isUserInteractionEnabled = isEnabled
|
||||
changeStateNoAnimation(isEnabled ? isOn : false)
|
||||
backgroundColor = isEnabled ? containerTintColor?.off : disabledTintColor?.container
|
||||
knobView.backgroundColor = isEnabled ? knobTintColor?.off : disabledTintColor?.knob
|
||||
backgroundColor = isEnabled ? (isOn ? containerTintColor.on : containerTintColor.off) : disabledTintColor.container
|
||||
knobView.backgroundColor = isEnabled ? (isOn ? knobTintColor.on : knobTintColor.off) : disabledTintColor.knob
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,12 +80,12 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
if isAnimated {
|
||||
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: {
|
||||
if self.isOn {
|
||||
self.knobView.backgroundColor = self.knobTintColor?.on
|
||||
self.backgroundColor = self.containerTintColor?.on
|
||||
self.knobView.backgroundColor = self.knobTintColor.on
|
||||
self.backgroundColor = self.containerTintColor.on
|
||||
|
||||
} else {
|
||||
self.knobView.backgroundColor = self.knobTintColor?.off
|
||||
self.backgroundColor = self.containerTintColor?.off
|
||||
self.knobView.backgroundColor = self.knobTintColor.off
|
||||
self.backgroundColor = self.containerTintColor.off
|
||||
}
|
||||
}, completion: nil)
|
||||
|
||||
@ -96,12 +96,12 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
}, completion: nil)
|
||||
|
||||
} else {
|
||||
backgroundColor = isOn ? containerTintColor?.on : containerTintColor?.off
|
||||
knobView.backgroundColor = isOn ? knobTintColor?.on : knobTintColor?.off
|
||||
backgroundColor = isOn ? containerTintColor.on : containerTintColor.off
|
||||
knobView.backgroundColor = isOn ? knobTintColor.on : knobTintColor.off
|
||||
self.constrainKnob()
|
||||
}
|
||||
|
||||
(model as? ToggleModel)?.state = isOn
|
||||
toggleModel?.state = isOn
|
||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff")
|
||||
setNeedsLayout()
|
||||
@ -109,6 +109,10 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
}
|
||||
}
|
||||
|
||||
public var toggleModel: ToggleModel? {
|
||||
return model as? ToggleModel
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate
|
||||
//--------------------------------------------------
|
||||
@ -189,7 +193,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
|
||||
public override func setupView() {
|
||||
super.setupView()
|
||||
guard subviews.isEmpty else { return }
|
||||
|
||||
isAccessibilityElement = true
|
||||
accessibilityTraits = .button
|
||||
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint")
|
||||
@ -202,7 +206,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
widthConstraint?.isActive = true
|
||||
|
||||
layer.cornerRadius = Self.containerSize.height / 2.0
|
||||
backgroundColor = containerTintColor?.off
|
||||
backgroundColor = containerTintColor.off
|
||||
|
||||
addSubview(knobView)
|
||||
|
||||
@ -222,9 +226,9 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
public override func reset() {
|
||||
super.reset()
|
||||
|
||||
backgroundColor = containerTintColor?.off
|
||||
knobView.backgroundColor = knobTintColor?.off
|
||||
isAnimated = false
|
||||
backgroundColor = containerTintColor.off
|
||||
knobView.backgroundColor = knobTintColor.off
|
||||
isAnimated = true
|
||||
isOn = false
|
||||
constrainKnob()
|
||||
didToggleAction = nil
|
||||
@ -344,26 +348,14 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
|
||||
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
|
||||
|
||||
if let color = model.onTintColor?.uiColor {
|
||||
containerTintColor?.on = color
|
||||
}
|
||||
|
||||
if let color = model.offTintColor?.uiColor {
|
||||
containerTintColor?.off = color
|
||||
}
|
||||
|
||||
if let color = model.onKnobTintColor?.uiColor {
|
||||
knobTintColor?.on = color
|
||||
}
|
||||
|
||||
if let color = model.offKnobTintColor?.uiColor {
|
||||
knobTintColor?.off = color
|
||||
}
|
||||
|
||||
containerTintColor.on = model.onTintColor.uiColor
|
||||
containerTintColor.off = model.offTintColor.uiColor
|
||||
knobTintColor.on = model.onKnobTintColor.uiColor
|
||||
knobTintColor.off = model.offKnobTintColor.uiColor
|
||||
changeStateNoAnimation(model.state)
|
||||
isAnimated = model.animated
|
||||
isEnabled = model.enabled
|
||||
|
||||
|
||||
if let actionMap = model.action?.toJSON() {
|
||||
didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) }
|
||||
}
|
||||
|
||||
@ -8,8 +8,12 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol {
|
||||
|
||||
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "toggle"
|
||||
public var backgroundColor: Color?
|
||||
public var state: Bool = false
|
||||
@ -18,10 +22,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
public var action: ActionModelProtocol?
|
||||
public var alternateAction: ActionModelProtocol?
|
||||
public var accessibilityText: String?
|
||||
public var onTintColor: Color?
|
||||
public var offTintColor: Color?
|
||||
public var onKnobTintColor: Color?
|
||||
public var offKnobTintColor: Color?
|
||||
public var onTintColor: Color = Color(uiColor: .mvmGreen)
|
||||
public var offTintColor: Color = Color(uiColor: .mvmBlack)
|
||||
public var onKnobTintColor: Color = Color(uiColor: .mvmWhite)
|
||||
public var offKnobTintColor: Color = Color(uiColor: .mvmWhite)
|
||||
|
||||
public var fieldKey: String?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
@ -75,19 +79,35 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
|
||||
self.state = state
|
||||
}
|
||||
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
|
||||
if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) {
|
||||
self.animated = animated
|
||||
}
|
||||
|
||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||
alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor)
|
||||
offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor)
|
||||
onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor)
|
||||
offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor)
|
||||
|
||||
if let onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor) {
|
||||
self.onTintColor = onTintColor
|
||||
}
|
||||
|
||||
if let offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor) {
|
||||
self.offTintColor = offTintColor
|
||||
}
|
||||
|
||||
if let onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor) {
|
||||
self.onKnobTintColor = onKnobTintColor
|
||||
}
|
||||
|
||||
if let offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor) {
|
||||
self.offKnobTintColor = offKnobTintColor
|
||||
}
|
||||
|
||||
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
|
||||
|
||||
baseValue = state
|
||||
@ -106,10 +126,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
try container.encode(state, forKey: .state)
|
||||
try container.encode(animated, forKey: .animated)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encodeIfPresent(onTintColor, forKey: .onTintColor)
|
||||
try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor)
|
||||
try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor)
|
||||
try container.encodeIfPresent(offKnobTintColor, forKey: .offKnobTintColor)
|
||||
try container.encode(onTintColor, forKey: .onTintColor)
|
||||
try container.encode(onKnobTintColor, forKey: .onKnobTintColor)
|
||||
try container.encode(onKnobTintColor, forKey: .onKnobTintColor)
|
||||
try container.encode(offKnobTintColor, forKey: .offKnobTintColor)
|
||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// GraphView.swift
|
||||
// Wheel.swift
|
||||
// MobileFirstFramework
|
||||
//
|
||||
// Created by Ryan on 10/24/19.
|
||||
@ -8,12 +8,12 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class GraphView: View, MVMCoreUIViewConstrainingProtocol {
|
||||
@objcMembers open class Wheel: View, MVMCoreUIViewConstrainingProtocol {
|
||||
|
||||
var heightConstraint: NSLayoutConstraint?
|
||||
var gradientLayer: CALayer?
|
||||
var graphModel: CircleProgressModel? {
|
||||
return model as? CircleProgressModel
|
||||
var graphModel: WheelModel? {
|
||||
return model as? WheelModel
|
||||
}
|
||||
|
||||
// MARK: setup
|
||||
@ -28,7 +28,7 @@ import UIKit
|
||||
|
||||
override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? CircleProgressModel else { return }
|
||||
guard let model = model as? WheelModel else { return }
|
||||
createGraphCircle(model)
|
||||
rotationAnimation(model)
|
||||
}
|
||||
@ -42,7 +42,7 @@ import UIKit
|
||||
}
|
||||
|
||||
// MARK: circle
|
||||
open func createGraphCircle(_ graphObject: CircleProgressModel) {
|
||||
open func createGraphCircle(_ graphObject: WheelModel) {
|
||||
if let sublayers = layer.sublayers {
|
||||
for sublayer in sublayers {
|
||||
sublayer.removeAllAnimations()
|
||||
@ -56,7 +56,7 @@ import UIKit
|
||||
|
||||
//begin point will be at the bottom, clockwise direction
|
||||
let path = UIBezierPath(arcCenter: CGPoint(x: radius
|
||||
, y: radius), radius: radius - graphObject.lineWidth/2.0, startAngle: CGFloat(GraphView.getPiValue(90.0)), endAngle: CGFloat(GraphView.getPiValue(90.0 + 360.0)), clockwise: true)
|
||||
, y: radius), radius: radius - graphObject.lineWidth/2.0, startAngle: CGFloat(Wheel.getPiValue(90.0)), endAngle: CGFloat(Wheel.getPiValue(90.0 + 360.0)), clockwise: true)
|
||||
path.lineWidth = graphObject.lineWidth
|
||||
|
||||
let circleLayer = CAShapeLayer()
|
||||
@ -83,7 +83,7 @@ import UIKit
|
||||
| | |
|
||||
-------------
|
||||
*/
|
||||
func createGradientLayer(_ graphObject: CircleProgressModel) -> CALayer {
|
||||
func createGradientLayer(_ graphObject: WheelModel) -> CALayer {
|
||||
let containLayer = CALayer()
|
||||
containLayer.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
|
||||
let radius = graphObject.diameter / 2.0
|
||||
@ -151,18 +151,18 @@ import UIKit
|
||||
}
|
||||
|
||||
//MARK: Animation
|
||||
func rotationAnimation(_ object: CircleProgressModel) {
|
||||
func rotationAnimation(_ object: WheelModel) {
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread:{
|
||||
let rotation = CABasicAnimation(keyPath: "transform.rotation")
|
||||
let animationHandler = GraphViewAnimationHandler.shared
|
||||
let animationHandler = WheelAnimationHandler.shared
|
||||
let startAngle = animationHandler.getAnimationStartAngle(object.duration, CACurrentMediaTime())
|
||||
if startAngle == 0.0 {
|
||||
animationHandler.storeAnimation(object.duration, CACurrentMediaTime())
|
||||
}
|
||||
var fromValue = GraphView.getPiValue(0.0 + startAngle), toValue = GraphView.getPiValue(360.0 + startAngle)
|
||||
var fromValue = Wheel.getPiValue(0.0 + startAngle), toValue = Wheel.getPiValue(360.0 + startAngle)
|
||||
if !object.clockwise {
|
||||
fromValue = GraphView.getPiValue(360.0 - startAngle)
|
||||
toValue = GraphView.getPiValue(0.0 - startAngle)
|
||||
fromValue = Wheel.getPiValue(360.0 - startAngle)
|
||||
toValue = Wheel.getPiValue(0.0 - startAngle)
|
||||
}
|
||||
rotation.fromValue = fromValue
|
||||
rotation.toValue = toValue
|
||||
@ -180,7 +180,7 @@ import UIKit
|
||||
}
|
||||
|
||||
|
||||
extension GraphView: CAAnimationDelegate {
|
||||
extension Wheel: CAAnimationDelegate {
|
||||
public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
|
||||
if let object = graphModel {
|
||||
rotationAnimation(object)
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// GraphViewAnimationHandler.swift
|
||||
// WheelAnimationHandler.swift
|
||||
// MobileFirstFramework
|
||||
//
|
||||
// Created by Ryan on 10/29/19.
|
||||
@ -8,12 +8,12 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class GraphViewAnimationHandler: NSObject {
|
||||
@objcMembers open class WheelAnimationHandler: NSObject {
|
||||
|
||||
/// duration : CACurrentMediaTime()
|
||||
private var animations = [Double: Double]()
|
||||
|
||||
static let shared = GraphViewAnimationHandler()
|
||||
static let shared = WheelAnimationHandler()
|
||||
|
||||
open func storeAnimation(_ duration: Double, _ currentTime: CFTimeInterval) {
|
||||
guard animations[duration] == nil else {
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// CircleProgressModel.swift
|
||||
// WheelModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 1/13/20.
|
||||
@ -16,9 +16,9 @@ public enum GraphStyle: String, Codable {
|
||||
case unlimited, safetyMode
|
||||
}
|
||||
|
||||
public class CircleProgressModel: MoleculeModelProtocol {
|
||||
public class WheelModel: MoleculeModelProtocol {
|
||||
|
||||
public static var identifier: String = "circleProgress"
|
||||
public static var identifier: String = "wheel"
|
||||
public var style: GraphStyle = .unlimited {
|
||||
didSet {
|
||||
updateStyle()
|
||||
@ -37,8 +37,7 @@ import Foundation
|
||||
/// Call to register all of the CoreUI molecules.
|
||||
public static func registerObjects() {
|
||||
// Stacks
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackView.self, viewModelClass: MoleculeStackModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Stack<StackModel>.self, viewModelClass: StackModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackView.self, viewModelClass: StackModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: UnOrderedList.self, viewModelClass: UnOrderedListModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: NumberedList.self, viewModelClass: NumberedListModel.self)
|
||||
|
||||
@ -70,6 +69,7 @@ import Foundation
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: RadioBoxes.self, viewModelClass: RadioBoxesModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatches.self, viewModelClass: RadioSwatchesModel.self)
|
||||
|
||||
// Other Atoms
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self)
|
||||
@ -78,7 +78,7 @@ import Foundation
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: DashLine.self, viewModelClass: DashLineModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: MFLoadImageView.self, viewModelClass: ImageViewModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Line.self, viewModelClass: LineModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: GraphView.self, viewModelClass: CircleProgressModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Wheel.self, viewModelClass: WheelModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Toggle.self, viewModelClass: ToggleModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: CheckboxLabel.self, viewModelClass: CheckboxLabelModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Arrow.self, viewModelClass: ArrowModel.self)
|
||||
@ -138,11 +138,14 @@ import Foundation
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonBodyText.self, viewModelClass: ListLeftVariableRadioButtonBodyTextModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableCheckboxBodyText.self, viewModelClass: ListLeftVariableCheckboxBodyTextModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTotalData.self, viewModelClass: ListRightVariableTotalDataModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTextLinkAllTextAndLinks.self, viewModelClass: ListRightVariableTextLinkAllTextAndLinksModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableButtonAllTextAndLinks.self, viewModelClass: ListRightVariableButtonAllTextAndLinksModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeBodyText.self, viewModelClass: ListRightVariablePriceChangeBodyTextModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeAllTextAndLinks.self, viewModelClass: ListRightVariablePriceChangeAllTextAndLinksModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextBodyText.self, viewModelClass: ListOneColumnFullWidthTextBodyTextModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self)
|
||||
@ -150,7 +153,7 @@ import Foundation
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self)
|
||||
|
||||
|
||||
// Designed Section Dividers
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self)
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
//
|
||||
// ListLeftVariableCheckboxBodyText.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 14/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class ListLeftVariableCheckboxBodyText: TableViewCell {
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
public let checkbox = Checkbox(frame: .zero)
|
||||
public var headlineBody = HeadlineBody()
|
||||
public var stack: Stack<StackModel>
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//-----------------------------------------------------
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
stack = Stack<StackModel>.createStack(with: [(view: checkbox, model: StackItemModel(horizontalAlignment: .fill)),
|
||||
(view: headlineBody, model: StackItemModel(horizontalAlignment: .leading))],
|
||||
axis: .horizontal)
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - View Lifecycle
|
||||
//-----------------------------------------------------
|
||||
override open func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
// MARK: - Molecule
|
||||
//----------------------------------------------------
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListLeftVariableCheckboxBodyTextModel else { return }
|
||||
checkbox.set(with: model.checkbox, delegateObject, additionalData)
|
||||
headlineBody.set(with: model.headlineBody, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return 90
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
//
|
||||
// ListLeftVariableCheckboxBodyTextModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 14/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
open class ListLeftVariableCheckboxBodyTextModel: ListItemModel, MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "listLVCBBdy"
|
||||
public var checkbox: CheckboxModel
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
public init(checkbox: CheckboxModel, headlineBody: HeadlineBodyModel) {
|
||||
self.checkbox = checkbox
|
||||
self.headlineBody = headlineBody
|
||||
super.init()
|
||||
}
|
||||
|
||||
open override func setDefaults() {
|
||||
super.setDefaults()
|
||||
headlineBody.style = .item
|
||||
if let headline = headlineBody.headline {
|
||||
headline.hero = 0
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case headlineBody
|
||||
case checkbox
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody)
|
||||
checkbox = try typeContainer.decode(CheckboxModel.self, forKey: .checkbox)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
open override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(headlineBody, forKey: .headlineBody)
|
||||
try container.encode(checkbox, forKey: .checkbox)
|
||||
}
|
||||
}
|
||||
@ -71,9 +71,6 @@ import UIKit
|
||||
}
|
||||
|
||||
public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
|
||||
if radioButton.isEnabled {
|
||||
radioButton.tapAction()
|
||||
}
|
||||
radioButton.tapAction()
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
@objcMembers open class ListRVWheel: TableViewCell {
|
||||
let wheel = GraphView(frame: .zero)
|
||||
let wheel = Wheel(frame: .zero)
|
||||
let leftLabel = Label.commonLabelB1(true)
|
||||
let rightLabel = Label.commonLabelB2(true)
|
||||
var stack: Stack<StackModel>
|
||||
|
||||
@ -11,9 +11,9 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "listRVWheel"
|
||||
public var leftLabel: LabelModel
|
||||
public var rightLabel: LabelModel
|
||||
public var wheel : CircleProgressModel
|
||||
public var wheel: WheelModel
|
||||
|
||||
public init(leftLabel: LabelModel, rightLabel: LabelModel, wheel: CircleProgressModel) {
|
||||
public init(leftLabel: LabelModel, rightLabel: LabelModel, wheel: WheelModel) {
|
||||
self.leftLabel = leftLabel
|
||||
self.rightLabel = rightLabel
|
||||
self.wheel = wheel
|
||||
@ -37,7 +37,7 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol {
|
||||
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()
|
||||
wheel = try typeContainer.decodeIfPresent(WheelModel.self, forKey: .wheel) ?? WheelModel()
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
//
|
||||
// ListRightVariablePriceChangeAllTextAndLinks.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 13/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class ListRightVariablePriceChangeAllTextAndLinks: TableViewCell {
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero)
|
||||
public let arrow = Arrow(frame: .zero)
|
||||
public let rightLabel = Label.commonLabelB2(true)
|
||||
private let stack: Stack<StackModel>
|
||||
private let arrowStackItem: StackItem
|
||||
private let rightLabelStackItem: StackItem
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//-----------------------------------------------------
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading),
|
||||
StackItemModel(horizontalAlignment: .fill),
|
||||
StackItemModel(spacing: 6, horizontalAlignment: .fill)],
|
||||
axis: .horizontal)
|
||||
arrowStackItem = StackItem(andContain: arrow)
|
||||
rightLabelStackItem = StackItem(andContain: rightLabel)
|
||||
let stackItems = [StackItem(andContain: eyebrowHeadlineBodyLink), arrowStackItem, rightLabelStackItem]
|
||||
stack = Stack<StackModel>(with: stackModel, stackItems: stackItems)
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - View Lifecycle
|
||||
//-----------------------------------------------------
|
||||
|
||||
open override func alignAccessoryToHero() -> CGPoint? {
|
||||
let heroCenter = super.alignAccessoryToHero()
|
||||
|
||||
// Aligns the center of the right side items to the headline.
|
||||
if let heroCenter = heroCenter {
|
||||
let convertedPoint = stack.convert(heroCenter, from: self)
|
||||
arrowStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - stack.bounds.midY
|
||||
rightLabelStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - stack.bounds.midY
|
||||
}
|
||||
return heroCenter
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
rightLabel.numberOfLines = 1
|
||||
|
||||
arrow.pinHeightAndWidth()
|
||||
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListRightVariablePriceChangeAllTextAndLinksModel else { return }
|
||||
eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData)
|
||||
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
|
||||
arrow.set(with: model.arrow, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return 121
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
//
|
||||
// ListRightVariablePriceChangeAllTextAndLinksModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 13/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ListRightVariablePriceChangeAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "listRVArwAll"
|
||||
public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel
|
||||
public var rightLabel: LabelModel
|
||||
public var arrow: ArrowModel
|
||||
|
||||
public init(eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel, rightLabel: LabelModel, arrow: ArrowModel) {
|
||||
self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink
|
||||
self.rightLabel = rightLabel
|
||||
self.arrow = arrow
|
||||
super.init()
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case eyebrowHeadlineBodyLink
|
||||
case rightLabel
|
||||
case arrow
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink)
|
||||
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
||||
arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow)
|
||||
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(rightLabel, forKey: .rightLabel)
|
||||
try container.encode(arrow, forKey: .arrow)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
//
|
||||
// ListRightVariablePriceChangeBodyText.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Dhamodaram Nandi on 13/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@objcMembers open class ListRightVariablePriceChangeBodyText: TableViewCell {
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
private let stack: Stack<StackModel>
|
||||
public let headlineBody = HeadlineBody(frame: .zero)
|
||||
public let arrow = Arrow(frame: .zero)
|
||||
public let rightLabel = Label.commonLabelB2(true)
|
||||
let arrowAndRightLabelStack: Stack<StackModel>
|
||||
|
||||
|
||||
// MARK: - Initializers
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
arrowAndRightLabelStack = Stack<StackModel>.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill)),
|
||||
(view: rightLabel, model: StackItemModel(horizontalAlignment: .fill))],
|
||||
axis: .horizontal, spacing: 6)
|
||||
stack = Stack<StackModel>.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .leading)),
|
||||
(view: arrowAndRightLabelStack, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .leading))],
|
||||
axis: .horizontal)
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - View Lifecycle
|
||||
//-----------------------------------------------------
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
headlineBody.styleListItem()
|
||||
|
||||
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
rightLabel.numberOfLines = 1
|
||||
|
||||
arrow.pinHeightAndWidth()
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
arrowAndRightLabelStack.restack()
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListRightVariablePriceChangeBodyTextModel else { return }
|
||||
headlineBody.set(with: model.headlineBody, delegateObject, additionalData)
|
||||
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
|
||||
arrow.set(with: model.arrow, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return 80
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
headlineBody.styleListItem()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
//
|
||||
// ListRightVariablePriceChangeBodyTextModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Dhamodaram Nandi on 13/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
public class ListRightVariablePriceChangeBodyTextModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "listRVArwBdy"
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
public var rightLabel: LabelModel
|
||||
public var arrow: ArrowModel
|
||||
|
||||
public init(headlineBody: HeadlineBodyModel,rightLabel: LabelModel,arrow: ArrowModel) {
|
||||
self.headlineBody = headlineBody
|
||||
self.rightLabel = rightLabel
|
||||
self.arrow = arrow
|
||||
super.init()
|
||||
}
|
||||
|
||||
/// Defaults to set
|
||||
public override func setDefaults() {
|
||||
super.setDefaults()
|
||||
if let headline = headlineBody.headline {
|
||||
headline.hero = 0
|
||||
}
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case headlineBody
|
||||
case rightLabel
|
||||
case arrow
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody)
|
||||
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
||||
arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow)
|
||||
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(headlineBody, forKey: .headlineBody)
|
||||
try container.encode(rightLabel, forKey: .rightLabel)
|
||||
try container.encode(arrow, forKey: .arrow)
|
||||
}
|
||||
}
|
||||
@ -86,7 +86,7 @@ import Foundation
|
||||
for item in model.sections {
|
||||
stackItems.append(MoleculeStackItemModel(with: item))
|
||||
}
|
||||
let stack = MoleculeStackModel(molecules: stackItems)
|
||||
let stack = StackModel(molecules: stackItems)
|
||||
stack.verticalAlignment = .fill
|
||||
colorLablesStack.set(with: stack, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol StackItemModelProtocol: MoleculeModelProtocol {
|
||||
public protocol StackItemModelProtocol {
|
||||
var spacing: CGFloat? { get set }
|
||||
var percent: Int? { get set }
|
||||
var gone: Bool { get set }
|
||||
|
||||
@ -164,10 +164,12 @@ import UIKit
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? CornerLabelsModel else { return }
|
||||
if middleView != nil {
|
||||
(middleView as? MoleculeViewProtocol)?.set(with: model, delegateObject, additionalData)
|
||||
} else if let moleculeModel = model.molecule, let molecule = MoleculeObjectMapping.shared()?.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) {
|
||||
addMiddleView(molecule)
|
||||
if let moleculeModel = model.molecule {
|
||||
if middleView != nil {
|
||||
(middleView as? MoleculeViewProtocol)?.set(with: moleculeModel, delegateObject, additionalData)
|
||||
} else if let molecule = MoleculeObjectMapping.shared()?.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) {
|
||||
addMiddleView(molecule)
|
||||
}
|
||||
}
|
||||
|
||||
topLeftLabel.setOptional(with: model.topLeftLabel, delegateObject, additionalData)
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class NumberedListModel: MoleculeStackModel {
|
||||
@objcMembers public class NumberedListModel: StackModel {
|
||||
public override class var identifier: String {
|
||||
return "numberedList"
|
||||
}
|
||||
@ -28,8 +28,7 @@ import Foundation
|
||||
for (index, molecule) in list.enumerated() {
|
||||
models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: "\(index+1).", molecule: molecule)))
|
||||
}
|
||||
super.init(molecules: models)
|
||||
spacing = 0
|
||||
super.init(molecules: models, spacing: 0)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
@ -39,7 +38,7 @@ import Foundation
|
||||
|
||||
var models: [MoleculeModelProtocol] = []
|
||||
for molecule in molecules {
|
||||
models.append(molecule.molecule)
|
||||
models.append(((molecule as! MoleculeStackItemModel).molecule as! StringAndMoleculeModel).molecule)
|
||||
}
|
||||
try container.encodeModels(models, forKey: .list)
|
||||
}
|
||||
|
||||
@ -11,8 +11,9 @@ import UIKit
|
||||
// This class is only temporarily necessary. Eventually we will have initWithModel instad of just init for moleculeviews, which will remove this need.
|
||||
open class StringAndMoleculeStack: MoleculeStackView {
|
||||
override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
guard let model = stackModel else { return }
|
||||
for stackItemModel in model.molecules {
|
||||
guard let model = model as? StackModelProtocol,
|
||||
let molcules = model.molecules as? [MoleculeStackItemModel] else { return }
|
||||
for stackItemModel in molcules {
|
||||
guard let stringAndMoleculeModel = stackItemModel.molecule as? StringAndMoleculeModel,
|
||||
let molecule = MoleculeObjectMapping.shared()?.createMolecule(stringAndMoleculeModel.molecule, delegateObject: delegateObject
|
||||
, additionalData: additionalData) else {
|
||||
|
||||
@ -10,7 +10,6 @@ import Foundation
|
||||
|
||||
open class StringAndMoleculeView: View {
|
||||
var label = Label.commonLabelB2(true)
|
||||
var string: String
|
||||
var molecule: MoleculeViewProtocol
|
||||
|
||||
var leftWidthConstraint: NSLayoutConstraint?
|
||||
@ -28,7 +27,7 @@ open class StringAndMoleculeView: View {
|
||||
|
||||
// MARK: - Inits
|
||||
public init(string: String, molecule: MoleculeViewProtocol) {
|
||||
self.string = string
|
||||
self.label.text = string
|
||||
self.molecule = molecule
|
||||
super.init(frame: .zero)
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class UnOrderedListModel: MoleculeStackModel {
|
||||
@objcMembers public class UnOrderedListModel: StackModel {
|
||||
public override class var identifier: String {
|
||||
return "unOrderedList"
|
||||
}
|
||||
@ -33,8 +33,7 @@ import Foundation
|
||||
for molecule in list {
|
||||
models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: bulletChar, molecule: molecule)))
|
||||
}
|
||||
super.init(molecules: models)
|
||||
spacing = 0
|
||||
super.init(molecules: models, spacing: 0)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
@ -45,7 +44,7 @@ import Foundation
|
||||
|
||||
var models: [MoleculeModelProtocol] = []
|
||||
for molecule in molecules {
|
||||
models.append(molecule.molecule)
|
||||
models.append(((molecule as! MoleculeStackItemModel).molecule as! StringAndMoleculeModel).molecule)
|
||||
}
|
||||
try container.encodeModels(models, forKey: .list)
|
||||
}
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
//
|
||||
// MoleculeStack.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 10/3/19.
|
||||
// Copyright © 2019 Suresh, Kamlesh. All rights reserved.
|
||||
//
|
||||
// A stack that has a list molecule stack items.
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class MoleculeStackModel: ContainerModel, MoleculeModelProtocol, StackModelProtocol {
|
||||
public class var identifier: String {
|
||||
return "stack"
|
||||
}
|
||||
public var backgroundColor: Color?
|
||||
public var molecules: [MoleculeStackItemModel]
|
||||
public var axis: NSLayoutConstraint.Axis = .vertical
|
||||
public var spacing: CGFloat = 16.0
|
||||
public var useStackSpacingBeforeFirstItem = false
|
||||
|
||||
public init(molecules: [MoleculeStackItemModel]) {
|
||||
self.molecules = molecules
|
||||
super.init()
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case molecules
|
||||
case axis
|
||||
case spacing
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
molecules = try typeContainer.decode([MoleculeStackItemModel].self, forKey: .molecules)
|
||||
if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) {
|
||||
axis = optionalAxis
|
||||
}
|
||||
if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) {
|
||||
self.spacing = spacing
|
||||
}
|
||||
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.encodeIfPresent(molecules, forKey: .molecules)
|
||||
try container.encodeIfPresent(axis.rawValueString, forKey: .axis)
|
||||
try container.encodeIfPresent(spacing, forKey: .spacing)
|
||||
}
|
||||
}
|
||||
@ -5,13 +5,12 @@
|
||||
// Created by Scott Pfeil on 2/11/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// This is a dynamic stack view that creates molecules if needed on set.
|
||||
|
||||
import UIKit
|
||||
|
||||
open class MoleculeStackView: Stack<MoleculeStackModel> {
|
||||
open override var stackModel: MoleculeStackModel? {
|
||||
get { return model as? MoleculeStackModel }
|
||||
}
|
||||
open class MoleculeStackView: Stack<StackModel> {
|
||||
var previousModel: MoleculeModelProtocol?
|
||||
|
||||
/// Convenience function, adds a molecule to a MoleculeStackItem to the MoleculeStack
|
||||
func setup(with views: [View], lastItem: Bool) {
|
||||
@ -26,14 +25,16 @@ open class MoleculeStackView: Stack<MoleculeStackModel> {
|
||||
if let stackModel = stackModel {
|
||||
stackModel.molecules = models
|
||||
} else {
|
||||
model = MoleculeStackModel(molecules: models)
|
||||
model = StackModel(molecules: models)
|
||||
}
|
||||
restack()
|
||||
}
|
||||
|
||||
|
||||
|
||||
// MARK: - Adding to stack
|
||||
/// Creates all of the stackItems for the stackItemModels
|
||||
override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
/// Can be subclassed to create views when we get stack item models and have no views yet
|
||||
open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
guard let stackItemModels = stackModel?.molecules else { return }
|
||||
for model in stackItemModels {
|
||||
if let stackItem = MoleculeObjectMapping.shared()?.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) as? MoleculeStackItem {
|
||||
@ -41,4 +42,20 @@ open class MoleculeStackView: Stack<MoleculeStackModel> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open override func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
// If the items in the stack are different, clear them, create new ones.
|
||||
if (previousModel == nil) || Self.nameForReuse(with: previousModel!, delegateObject) != Self.nameForReuse(with: model, delegateObject) {
|
||||
removeAllItemViews()
|
||||
stackItems = []
|
||||
createStackItemsFromModel(model, delegateObject, additionalData)
|
||||
} else {
|
||||
super.setStackItemsFromModel(model, delegateObject, additionalData)
|
||||
}
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
previousModel = self.model
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,18 +147,8 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
let previousModel = self.model
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
removeAllItemViews()
|
||||
|
||||
// If the items in the stack are different, clear them, create new ones.
|
||||
if (previousModel == nil) || Self.nameForReuse(with: previousModel!, delegateObject) != Self.nameForReuse(with: model, delegateObject) {
|
||||
stackItems = []
|
||||
createStackItemsFromModel(model, delegateObject, additionalData)
|
||||
} else {
|
||||
setStackItemsFromModel(model, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
setStackItemsFromModel(model, delegateObject, additionalData)
|
||||
restack()
|
||||
}
|
||||
|
||||
@ -216,9 +206,6 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
|
||||
// MARK: - Subclassables
|
||||
//--------------------------------------------------
|
||||
|
||||
/// Can be subclassed to create views when we get stack item models and have no views yet
|
||||
open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { }
|
||||
|
||||
/// Can be subclassed to set stack items with model when we already have views
|
||||
open func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let models = stackModel?.molecules else { return }
|
||||
@ -243,10 +230,10 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
|
||||
}
|
||||
|
||||
/// Sets the stack with StackItems containing the passed in views and sets the StackModel with models.
|
||||
open func set(with viewModels:[(view: UIView, model: T.AnyStackItemModel)]) {
|
||||
open func set(with viewModels:[(view: UIView, model: StackItemModel)]) {
|
||||
guard var stackModel = self.stackModel else { return }
|
||||
var stackItems: [StackItem] = []
|
||||
var models: [T.AnyStackItemModel] = []
|
||||
var models: [StackItemModel] = []
|
||||
for item in viewModels {
|
||||
stackItems.append(StackItem(andContain: item.view))
|
||||
models.append(item.model)
|
||||
@ -307,7 +294,7 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
|
||||
if let percent = model.percent {
|
||||
let multiplier = CGFloat(percent) / 100.0
|
||||
let constant = multiplier * totalSpacing
|
||||
view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: multiplier, constant: -constant).isActive = true
|
||||
view.heightAnchor.constraint(equalTo: heightAnchor, multiplier: multiplier, constant: -constant).isActive = true
|
||||
}
|
||||
if lastItem {
|
||||
pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
|
||||
@ -326,7 +313,7 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
|
||||
if let percent = model.percent {
|
||||
let multiplier = CGFloat(percent) / 100.0
|
||||
let constant = multiplier * totalSpacing
|
||||
view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: multiplier, constant: -constant).isActive = true
|
||||
view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: multiplier, constant: -constant).isActive = true
|
||||
}
|
||||
if lastItem {
|
||||
pinView(contentView, toView: view, attribute: .right, relation: .equal, priority: .required, constant: 0)
|
||||
|
||||
@ -8,17 +8,19 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class StackModel: StackModelProtocol, MoleculeModelProtocol {
|
||||
@objcMembers public class StackModel: ContainerModel, StackModelProtocol, MoleculeModelProtocol {
|
||||
static let defaultSpacing: CGFloat = 16.0
|
||||
|
||||
public static var identifier: String = "simpleStack"
|
||||
public class var identifier: String {
|
||||
return "stack"
|
||||
}
|
||||
public var backgroundColor: Color?
|
||||
public var molecules: [StackItemModel]
|
||||
public var molecules: [StackItemModelProtocol & MoleculeModelProtocol]
|
||||
public var axis: NSLayoutConstraint.Axis = .vertical
|
||||
public var spacing: CGFloat = StackModel.defaultSpacing
|
||||
public var useStackSpacingBeforeFirstItem = false
|
||||
|
||||
public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) {
|
||||
public init(molecules: [StackItemModelProtocol & MoleculeModelProtocol], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) {
|
||||
self.molecules = molecules
|
||||
if let axis = axis {
|
||||
self.axis = axis
|
||||
@ -26,6 +28,7 @@ import Foundation
|
||||
if let spacing = spacing {
|
||||
self.spacing = spacing
|
||||
}
|
||||
super.init()
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
@ -38,19 +41,20 @@ import Foundation
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
molecules = try typeContainer.decode([StackItemModel].self, forKey: .molecules)
|
||||
molecules = try typeContainer.decodeModels(codingKey: .molecules)
|
||||
if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) {
|
||||
axis = optionalAxis
|
||||
}
|
||||
if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) {
|
||||
self.spacing = spacing
|
||||
}
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(molecules, forKey: .molecules)
|
||||
try container.encodeModels(molecules, forKey: .molecules)
|
||||
try container.encodeIfPresent(axis.rawValueString, forKey: .axis)
|
||||
try container.encodeIfPresent(spacing, forKey: .spacing)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
|
||||
@ -9,9 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
public protocol StackModelProtocol {
|
||||
associatedtype AnyStackItemModel: StackItemModelProtocol
|
||||
|
||||
var molecules: [AnyStackItemModel] { get set }
|
||||
var molecules: [StackItemModelProtocol & MoleculeModelProtocol] { get set }
|
||||
var axis: NSLayoutConstraint.Axis { get set }
|
||||
var spacing: CGFloat { get set }
|
||||
var useStackSpacingBeforeFirstItem: Bool { get set }
|
||||
|
||||
@ -15,10 +15,10 @@ import Foundation
|
||||
}
|
||||
|
||||
public var header: MoleculeModelProtocol?
|
||||
public var moleculeStack: MoleculeStackModel
|
||||
public var moleculeStack: StackModel
|
||||
public var footer: MoleculeModelProtocol?
|
||||
|
||||
public init(pageType: String, moleculeStack: MoleculeStackModel) {
|
||||
public init(pageType: String, moleculeStack: StackModel) {
|
||||
self.moleculeStack = moleculeStack
|
||||
super.init(pageType: pageType)
|
||||
}
|
||||
@ -31,7 +31,7 @@ import Foundation
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .stack)
|
||||
moleculeStack = try typeContainer.decode(StackModel.self, forKey: .stack)
|
||||
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
|
||||
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
|
||||
try super.init(from: decoder)
|
||||
|
||||
@ -26,7 +26,7 @@ import UIKit
|
||||
/// For subclasses that want to use a custom accessory view.
|
||||
open var customAccessoryView = false
|
||||
|
||||
private var heroAccessoryCenter: CGPoint?
|
||||
public var heroAccessoryCenter: CGPoint?
|
||||
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
@ -97,7 +97,7 @@ import UIKit
|
||||
|
||||
// Ensures accessory view aligns to the center y derived from the
|
||||
if let _ = heroAccessoryCenter {
|
||||
alignAccessoryToHero()
|
||||
_ = alignAccessoryToHero()
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,14 +215,16 @@ import UIKit
|
||||
}
|
||||
|
||||
/// NOTE: Should only be called when displayed or about to be displayed.
|
||||
public func alignAccessoryToHero() {
|
||||
public func alignAccessoryToHero() -> CGPoint? {
|
||||
|
||||
// Layout call required to force draw in memory to get dimensions of subviews.
|
||||
layoutIfNeeded()
|
||||
guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return }
|
||||
guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return nil }
|
||||
let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel)
|
||||
accessoryView?.center.y = convert(UIView(frame: rect).center, from: heroLabel).y
|
||||
let y = convert(UIView(frame: rect).center, from: heroLabel).y
|
||||
accessoryView?.center.y = y
|
||||
heroAccessoryCenter = accessoryView?.center
|
||||
return heroAccessoryCenter ?? CGPoint(x: 0, y: y)
|
||||
}
|
||||
|
||||
/// Traverses the view hierarchy for a 🦸♂️ heroic Label.
|
||||
@ -269,7 +271,7 @@ import UIKit
|
||||
}
|
||||
|
||||
public func willDisplay() {
|
||||
alignAccessoryToHero()
|
||||
_ = alignAccessoryToHero()
|
||||
}
|
||||
|
||||
// MARK: - Separator
|
||||
|
||||
@ -236,10 +236,13 @@ import UIKit
|
||||
}
|
||||
|
||||
// MARK: - View lifecycle
|
||||
|
||||
/// Called only once in viewDidLoad
|
||||
open func initialLoad() {
|
||||
observeForResponseJSONUpdates()
|
||||
}
|
||||
|
||||
/// Called on screen size update.
|
||||
open func updateViews() {
|
||||
_ = formValidator?.validate()
|
||||
}
|
||||
@ -265,10 +268,7 @@ import UIKit
|
||||
initialLoad()
|
||||
}
|
||||
|
||||
// Handle data for first load. Dispatched to allow subclasses to finish their view did load implementations.
|
||||
DispatchQueue.main.async {
|
||||
self.handleNewDataAndUpdateUI()
|
||||
}
|
||||
handleNewDataAndUpdateUI()
|
||||
}
|
||||
|
||||
open override func viewDidLayoutSubviews() {
|
||||
@ -292,8 +292,10 @@ import UIKit
|
||||
open override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
// Update the navigation bar ui when view is appearing
|
||||
setNavigationController()
|
||||
// Update the navigation bar ui when view is appearing. Can remove check in the future, see viewControllerReady
|
||||
if manager == nil {
|
||||
setNavigationController()
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewDidAppear(_ animated: Bool) {
|
||||
@ -326,6 +328,10 @@ import UIKit
|
||||
|
||||
// MARK: - MVMCoreViewManagerViewControllerProtocol
|
||||
open func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) {
|
||||
// TODO: This check and set aren't technically needed anymore. The one in viewwillappear should be enough. However, there is a timing issue with the manager where the screen lays out before the menu shows, so the screen grows off the screen. Can fix in the future.
|
||||
if let _ = self.view {
|
||||
setNavigationController()
|
||||
}
|
||||
// Janky way to track current page.
|
||||
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
|
||||
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user