Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui into feature/circular_progress_bar

This commit is contained in:
Prateek Arora 2020-02-18 13:42:31 +05:30
commit f8fea032b5
80 changed files with 1462 additions and 774 deletions

View File

@ -27,6 +27,7 @@
012A88F123985E0100FE3DA1 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88F023985E0100FE3DA1 /* Color.swift */; }; 012A88F123985E0100FE3DA1 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88F023985E0100FE3DA1 /* Color.swift */; };
012CA99A2384A687003F810F /* MFTextField+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */; }; 012CA99A2384A687003F810F /* MFTextField+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */; };
012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */; }; 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */; };
013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */; };
014AA72423C501E2006F3E93 /* MoleculeContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */; }; 014AA72423C501E2006F3E93 /* MoleculeContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */; };
014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72223C501E2006F3E93 /* ContainerModel.swift */; }; 014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72223C501E2006F3E93 /* ContainerModel.swift */; };
014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */; }; 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */; };
@ -54,7 +55,7 @@
01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */; }; 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */; };
01EB368F23609801006832FA /* LabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368823609801006832FA /* LabelModel.swift */; }; 01EB368F23609801006832FA /* LabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368823609801006832FA /* LabelModel.swift */; };
01EB369023609801006832FA /* ListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368923609801006832FA /* ListItemModel.swift */; }; 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368923609801006832FA /* MoleculeListItemModel.swift */; };
01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368B23609801006832FA /* MoleculeStackModel.swift */; }; 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368B23609801006832FA /* MoleculeStackModel.swift */; };
01EB369323609801006832FA /* HeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368C23609801006832FA /* HeaderModel.swift */; }; 01EB369323609801006832FA /* HeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368C23609801006832FA /* HeaderModel.swift */; };
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368D23609801006832FA /* HeadlineBodyModel.swift */; }; 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368D23609801006832FA /* HeadlineBodyModel.swift */; };
@ -95,6 +96,10 @@
0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; }; 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; };
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; }; 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; };
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; }; 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; };
5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; };
5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */; };
8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; };
8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */; };
9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; }; 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; };
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; };
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; };
@ -167,6 +172,7 @@
D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; }; D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; };
D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; }; D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; };
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */; };
D274CA332236A78900B01B62 /* FooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* FooterView.swift */; }; D274CA332236A78900B01B62 /* FooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* FooterView.swift */; };
D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2755D7A23689C7500485468 /* TableViewCell.swift */; }; D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2755D7A23689C7500485468 /* TableViewCell.swift */; };
D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */; }; D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */; };
@ -309,6 +315,7 @@
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */; }; D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */; };
D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; }; D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; };
D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C521A823EDE79E00CA2634 /* ViewController.swift */; };
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; }; D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; };
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; }; D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; };
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; }; D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; };
@ -329,7 +336,7 @@
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; }; DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; };
DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; }; DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; };
DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; }; DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; };
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391A224421A0001AB423 /* CaretButton.swift */; }; DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391A224421A0001AB423 /* CaretLink.swift */; };
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */; }; DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */; };
DBEFFA04225A829700230692 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB891E822253FA8500022516 /* Label.swift */; }; DBEFFA04225A829700230692 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB891E822253FA8500022516 /* Label.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -355,6 +362,7 @@
012A88F023985E0100FE3DA1 /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = "<group>"; }; 012A88F023985E0100FE3DA1 /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = "<group>"; };
012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFTextField+ModelExtension.swift"; sourceTree = "<group>"; }; 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFTextField+ModelExtension.swift"; sourceTree = "<group>"; };
012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFView+ModelExtension.swift"; sourceTree = "<group>"; }; 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFView+ModelExtension.swift"; sourceTree = "<group>"; };
013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIContentMode+Extension.swift"; sourceTree = "<group>"; };
014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeContainerModel.swift; sourceTree = "<group>"; }; 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeContainerModel.swift; sourceTree = "<group>"; };
014AA72223C501E2006F3E93 /* ContainerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainerModel.swift; sourceTree = "<group>"; }; 014AA72223C501E2006F3E93 /* ContainerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainerModel.swift; sourceTree = "<group>"; };
014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainerModelProtocol.swift; sourceTree = "<group>"; }; 014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainerModelProtocol.swift; sourceTree = "<group>"; };
@ -381,7 +389,7 @@
01C851D223CF9E740021F976 /* LabelToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggleModel.swift; sourceTree = "<group>"; }; 01C851D223CF9E740021F976 /* LabelToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggleModel.swift; sourceTree = "<group>"; };
01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeModelProtocol.swift; sourceTree = "<group>"; }; 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeModelProtocol.swift; sourceTree = "<group>"; };
01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = "<group>"; }; 01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = "<group>"; };
01EB368923609801006832FA /* ListItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListItemModel.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>"; }; 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>"; }; 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>"; }; 01EB368C23609801006832FA /* HeaderModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderModel.swift; sourceTree = "<group>"; };
@ -414,6 +422,10 @@
0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; }; 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = "<group>"; }; 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = "<group>"; };
31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = "<group>"; }; 31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = "<group>"; };
5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = "<group>"; };
5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDividerModel.swift; sourceTree = "<group>"; };
8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = "<group>"; };
8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaretModel.swift; sourceTree = "<group>"; };
9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; }; 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; };
9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.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>"; }; 943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = "<group>"; };
@ -484,6 +496,7 @@
D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIPageControl.m; sourceTree = "<group>"; }; D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIPageControl.m; sourceTree = "<group>"; };
D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = "<group>"; }; D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = "<group>"; };
D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = "<group>"; }; D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = "<group>"; };
D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemModel.swift; sourceTree = "<group>"; };
D274CA322236A78900B01B62 /* FooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterView.swift; sourceTree = "<group>"; }; D274CA322236A78900B01B62 /* FooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterView.swift; sourceTree = "<group>"; };
D2755D7A23689C7500485468 /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = "<group>"; }; D2755D7A23689C7500485468 /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = "<group>"; };
D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewCell.swift; sourceTree = "<group>"; }; D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewCell.swift; sourceTree = "<group>"; };
@ -641,6 +654,7 @@
D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageHeadlineBody.swift; sourceTree = "<group>"; }; D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageHeadlineBody.swift; sourceTree = "<group>"; };
D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = "<group>"; }; D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = "<group>"; };
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = "<group>"; }; D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = "<group>"; };
D2C521A823EDE79E00CA2634 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = "<group>"; }; D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = "<group>"; };
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = "<group>"; }; D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = "<group>"; };
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; }; D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
@ -655,14 +669,13 @@
D2E2A99E23E07F8A000B42E6 /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; }; D2E2A99E23E07F8A000B42E6 /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; };
D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModelProtocol.swift; sourceTree = "<group>"; }; D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModelProtocol.swift; sourceTree = "<group>"; };
D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableableModelProtocol.swift; sourceTree = "<group>"; }; D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableableModelProtocol.swift; sourceTree = "<group>"; };
D2F4DDE52371A4CB00CD28BB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainer.swift; sourceTree = "<group>"; }; D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainer.swift; sourceTree = "<group>"; };
D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackItem.swift; sourceTree = "<group>"; }; D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackItem.swift; sourceTree = "<group>"; };
DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeftRightLabelView.swift; sourceTree = "<group>"; }; DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeftRightLabelView.swift; sourceTree = "<group>"; };
DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; }; DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = "<group>"; }; DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = "<group>"; };
DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = "<group>"; }; DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = "<group>"; };
DBC4391A224421A0001AB423 /* CaretButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretButton.swift; sourceTree = "<group>"; }; DBC4391A224421A0001AB423 /* CaretLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretLink.swift; sourceTree = "<group>"; };
DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelWithInternalButton.swift; sourceTree = "<group>"; }; DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelWithInternalButton.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -839,6 +852,8 @@
D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */, D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */,
D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */, D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */,
D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */, D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */,
94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */,
94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */,
D282AACA2243C61700C46919 /* ButtonView.swift */, D282AACA2243C61700C46919 /* ButtonView.swift */,
94AF4A3C23E9D13900676048 /* MFCaretButton.h */, 94AF4A3C23E9D13900676048 /* MFCaretButton.h */,
94AF4A3D23E9D13900676048 /* MFCaretButton.m */, 94AF4A3D23E9D13900676048 /* MFCaretButton.m */,
@ -889,8 +904,6 @@
D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */, D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */,
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */, D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */,
D28A837E23CCA96400DFE4FC /* TabsModel.swift */, D28A837E23CCA96400DFE4FC /* TabsModel.swift */,
94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */,
94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */,
); );
path = HorizontalCombinationViews; path = HorizontalCombinationViews;
sourceTree = "<group>"; sourceTree = "<group>";
@ -924,8 +937,8 @@
D22479912316A9EF003FCCF9 /* Items */ = { D22479912316A9EF003FCCF9 /* Items */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D2755D7A23689C7500485468 /* TableViewCell.swift */, D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */,
01EB368923609801006832FA /* ListItemModel.swift */, 01EB368923609801006832FA /* MoleculeListItemModel.swift */,
01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */, 01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */,
012A88C1238D7BCA00FE3DA1 /* CarouselItemModel.swift */, 012A88C1238D7BCA00FE3DA1 /* CarouselItemModel.swift */,
D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */, D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */,
@ -944,6 +957,49 @@
path = Items; path = Items;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D22B38E923F4E07800490EF6 /* DesignedComponents */ = {
isa = PBXGroup;
children = (
D22B38EC23F4E10700490EF6 /* SectionDividers */,
D22B38EA23F4E08B00490EF6 /* List */,
);
path = DesignedComponents;
sourceTree = "<group>";
};
D22B38EA23F4E08B00490EF6 /* List */ = {
isa = PBXGroup;
children = (
D22B38EB23F4E0AE00490EF6 /* LeftVariable */,
);
path = List;
sourceTree = "<group>";
};
D22B38EB23F4E0AE00490EF6 /* LeftVariable */ = {
isa = PBXGroup;
children = (
8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */,
8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */,
);
path = LeftVariable;
sourceTree = "<group>";
};
D22B38EC23F4E10700490EF6 /* SectionDividers */ = {
isa = PBXGroup;
children = (
D22B38ED23F4E11100490EF6 /* ThreeColumn */,
);
path = SectionDividers;
sourceTree = "<group>";
};
D22B38ED23F4E11100490EF6 /* ThreeColumn */ = {
isa = PBXGroup;
children = (
5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */,
5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */,
);
path = ThreeColumn;
sourceTree = "<group>";
};
D22D1F582204D2590077CEC0 /* Legacy */ = { D22D1F582204D2590077CEC0 /* Legacy */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1046,6 +1102,7 @@
D29DF10E21E67A77003B2FB9 /* Molecules */ = { D29DF10E21E67A77003B2FB9 /* Molecules */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D22B38E923F4E07800490EF6 /* DesignedComponents */,
D22479912316A9EF003FCCF9 /* Items */, D22479912316A9EF003FCCF9 /* Items */,
D224798F2316A99F003FCCF9 /* LeftRightViews */, D224798F2316A99F003FCCF9 /* LeftRightViews */,
D224798E2316A995003FCCF9 /* HorizontalCombinationViews */, D224798E2316A995003FCCF9 /* HorizontalCombinationViews */,
@ -1085,7 +1142,7 @@
D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */, D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */,
D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */, D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */,
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */, D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */,
D2F4DDE52371A4CB00CD28BB /* ViewController.swift */, D2C521A823EDE79E00CA2634 /* ViewController.swift */,
); );
path = BaseControllers; path = BaseControllers;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1093,6 +1150,7 @@
D29DF11021E6805F003B2FB9 /* Categories */ = { D29DF11021E6805F003B2FB9 /* Categories */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */,
D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */, D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */,
D29DF11321E6805F003B2FB9 /* UIColor+MFConvenience.m */, D29DF11321E6805F003B2FB9 /* UIColor+MFConvenience.m */,
D29DF11221E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h */, D29DF11221E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h */,
@ -1174,7 +1232,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
01F2A03123A4498200D954D8 /* CaretLinkModel.swift */, 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */,
DBC4391A224421A0001AB423 /* CaretButton.swift */, DBC4391A224421A0001AB423 /* CaretLink.swift */,
D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */, D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */,
D2E2A99E23E07F8A000B42E6 /* PillButton.swift */, D2E2A99E23E07F8A000B42E6 /* PillButton.swift */,
D28A838823CCCFCB00DFE4FC /* LinkModel.swift */, D28A838823CCCFCB00DFE4FC /* LinkModel.swift */,
@ -1383,6 +1441,7 @@
D2B18B7E2360913400A9AEDC /* Control.swift */, D2B18B7E2360913400A9AEDC /* Control.swift */,
D2B18B802360945C00A9AEDC /* View.swift */, D2B18B802360945C00A9AEDC /* View.swift */,
0AE14F63238315D2005417F8 /* TextField.swift */, 0AE14F63238315D2005417F8 /* TextField.swift */,
D2755D7A23689C7500485468 /* TableViewCell.swift */,
0A5D59C323AD488600EFD9E9 /* Protocols */, 0A5D59C323AD488600EFD9E9 /* Protocols */,
); );
path = BaseClasses; path = BaseClasses;
@ -1547,6 +1606,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */,
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */, 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */,
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */, 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */,
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */, 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */,
@ -1635,7 +1695,7 @@
012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */, 012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */,
D2A514672213885800345BFB /* HeaderView.swift in Sources */, D2A514672213885800345BFB /* HeaderView.swift in Sources */,
D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */,
01EB369023609801006832FA /* ListItemModel.swift in Sources */, 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */,
D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */, D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */,
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */,
DBEFFA04225A829700230692 /* Label.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */,
@ -1645,6 +1705,7 @@
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */, 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */,
D260105523CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift in Sources */, D260105523CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift in Sources */,
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */,
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */, 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */,
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */, 0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */,
94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */, 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */,
@ -1695,6 +1756,7 @@
94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */, 94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */,
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */,
D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */, D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */,
012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */, 012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */,
D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */,
@ -1708,6 +1770,7 @@
D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */,
D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */, D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */,
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */,
8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */,
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */,
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */,
0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */, 0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */,
@ -1727,6 +1790,7 @@
D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */,
0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */, 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */,
D243859923A16B1800332775 /* Container.swift in Sources */, D243859923A16B1800332775 /* Container.swift in Sources */,
D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */,
D260105B23D0BB7100764D80 /* StackModelProtocol.swift in Sources */, D260105B23D0BB7100764D80 /* StackModelProtocol.swift in Sources */,
D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */, D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */,
D28A839323CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift in Sources */, D28A839323CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift in Sources */,
@ -1742,11 +1806,13 @@
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */, D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */,
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */, D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */,
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */, 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */, 0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */,
94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */, 94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */,
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */, 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */,
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */,
013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */,
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */, D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */,
D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */,
@ -1758,7 +1824,7 @@
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */,
D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */, D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */,
C003506123AA94CD00B6AC29 /* Button.swift in Sources */, C003506123AA94CD00B6AC29 /* Button.swift in Sources */,
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */, DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */,
0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */, 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */,
0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */, 0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */,
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */, 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */,

View File

@ -20,7 +20,6 @@ public enum ButtonSize: String, Codable {
public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol {
public static var identifier: String = "button" public static var identifier: String = "button"
public var moleculeName: String?
public var backgroundColor: Color? public var backgroundColor: Color?
public var title: String public var title: String
public var action: ActionModelProtocol public var action: ActionModelProtocol
@ -41,6 +40,18 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol {
self.action = action self.action = action
} }
init(secondaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
style = .secondary
}
init(primaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
style = .primary
}
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case backgroundColor case backgroundColor
@ -61,7 +72,6 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol {
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
title = try typeContainer.decode(String.self, forKey: .title) title = try typeContainer.decode(String.self, forKey: .title)

View File

@ -1,5 +1,5 @@
// //
// CaretButton.swift // CaretLink.swift
// MVMCoreUI // MVMCoreUI
// //
// Created by Kolli, Praneeth on 1/5/18. // Created by Kolli, Praneeth on 1/5/18.
@ -8,7 +8,7 @@
// //
open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, ModelMoleculeViewProtocol { open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol {
//------------------------------------------------------ //------------------------------------------------------
// MARK: - Constants // MARK: - Constants
@ -49,7 +49,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
didSet { changeCaretColor() } didSet { changeCaretColor() }
} }
public func updateView(_ size: CGFloat) { public override func updateView(_ size: CGFloat) {
titleLabel?.font = MFStyler.fontB1() titleLabel?.font = MFStyler.fontB1()
} }
@ -125,33 +125,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
setTitleColor(disabledColor, for: .disabled) setTitleColor(disabledColor, for: .disabled)
} }
@objc public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
setWithActionMap(json, delegateObject: delegateObject, additionalData: additionalData)
guard let dictionary = json else { return }
if let title = dictionary.optionalStringForKey(KeyTitle) {
setTitle(title, for: .normal)
}
if let disableButtonAsAny = dictionary[KeyDisableButton], let isDisabled = disableButtonAsAny as? Bool {
isEnabled = !isDisabled
}
if let backgroundColorHex = dictionary[KeyBackgroundColor] as? String {
backgroundColor = UIColor.mfGet(forHex: backgroundColorHex)
}
if let enabledColorHex = dictionary["enabledColor"] as? String {
enabledColor = UIColor.mfGet(forHex: enabledColorHex)
}
if let disabledColorHex = dictionary["disabledColor"] as? String {
disabledColor = UIColor.mfGet(forHex: disabledColorHex)
}
}
public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let caretLinkModel = model as? CaretLinkModel else { return } guard let caretLinkModel = model as? CaretLinkModel else { return }
if let color = caretLinkModel.backgroundColor { if let color = caretLinkModel.backgroundColor {
backgroundColor = color.uiColor backgroundColor = color.uiColor
@ -173,7 +147,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
return .leading return .leading
} }
public class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 10 return 10.5
} }
} }

View File

@ -97,9 +97,9 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol, FormValidation
public static func getHeight(for buttonSize: ButtonSize?, size: CGFloat) -> CGFloat { public static func getHeight(for buttonSize: ButtonSize?, size: CGFloat) -> CGFloat {
switch buttonSize { switch buttonSize {
case .tiny: case .tiny:
return MFSizeObject(standardSize: ButtonHeight.tiny.rawValue, standardiPadPortraitSize: 34, iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? 20 return MFSizeObject(standardSize: ButtonHeight.tiny.rawValue, standardiPadPortraitSize: 34, iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? ButtonHeight.tiny.rawValue
default: default:
return MFSizeObject(standardSize: ButtonHeight.standard.rawValue, standardiPadPortraitSize: 46, iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? 42 return MFSizeObject(standardSize: ButtonHeight.standard.rawValue, standardiPadPortraitSize: 46, iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? ButtonHeight.standard.rawValue
} }
} }
@ -108,7 +108,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol, FormValidation
case .tiny: case .tiny:
return MFSizeObject(standardSize: 49.0, standardiPadPortraitSize: 90.0, iPadProLandscapeSize: 135.0)?.getValueBased(onSize: size) ?? 49.0 return MFSizeObject(standardSize: 49.0, standardiPadPortraitSize: 90.0, iPadProLandscapeSize: 135.0)?.getValueBased(onSize: size) ?? 49.0
default: default:
return MFSizeObject(standardSize: 102.0, standardiPadPortraitSize: 136.0, iPadProLandscapeSize: 153.0)?.getValueBased(onSize: size) ?? 102.0 return 151.0
} }
} }

View File

@ -21,7 +21,7 @@ import UIKit
let caret = CaretView() let caret = CaretView()
caret.direction = .down caret.direction = .down
caret.lineWidth = 1.5 caret.lineWidth = 1.5
caret.isUserInteractionEnabled = true caret.isUserInteractionEnabled = false
caret.heightAnchor.constraint(equalToConstant: 9).isActive = true caret.heightAnchor.constraint(equalToConstant: 9).isActive = true
caret.widthAnchor.constraint(equalToConstant: 16).isActive = true caret.widthAnchor.constraint(equalToConstant: 16).isActive = true
return caret return caret

View File

@ -37,7 +37,7 @@ import Foundation
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case backgroundColor case backgroundColor
case title case title = "label"
case isEnabled case isEnabled
case feedback case feedback
case errorMessage = "errorMsg" case errorMessage = "errorMsg"

View File

@ -26,6 +26,10 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
/// Closure passed here will run upon dismissing the selection picker. /// Closure passed here will run upon dismissing the selection picker.
public var observeDropdownSelection: ((String)->())? public var observeDropdownSelection: ((String)->())?
public var itemDropdownEntryFieldModel: ItemDropdownEntryFieldModel? {
return model as? ItemDropdownEntryFieldModel
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -100,7 +104,7 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
setPickerDelegates(delegate: self) setPickerDelegates(delegate: self)
if let pickerView = pickerView { if let pickerView = pickerView {
self.pickerView(pickerView, didSelectRow: 0, inComponent: 0) self.pickerView(pickerView, didSelectRow: model.selectedIndex, inComponent: 0)
} }
} }
} }
@ -127,6 +131,7 @@ extension ItemDropdownEntryField: UIPickerViewDelegate, UIPickerViewDataSource {
observeDropdownChange?(text ?? "", pickerData[row]) observeDropdownChange?(text ?? "", pickerData[row])
text = pickerData[row] text = pickerData[row]
itemDropdownEntryFieldModel?.selectedIndex = row
} }
} }

View File

@ -16,6 +16,7 @@
} }
public var options: [String] = [] public var options: [String] = []
public var selectedIndex: Int = 0
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
@ -24,6 +25,7 @@
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case options case options
case selectedIndex
} }
//-------------------------------------------------- //--------------------------------------------------
@ -34,6 +36,7 @@
try super.init(from: decoder) try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
options = try typeContainer.decode([String].self, forKey: .options) options = try typeContainer.decode([String].self, forKey: .options)
selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) ?? 0
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
@ -41,5 +44,6 @@
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(options, forKey: .options) try container.encode(options, forKey: .options)
try container.encode(options, forKey: .selectedIndex)
} }
} }

View File

@ -9,7 +9,7 @@
import UIKit import UIKit
@objc public protocol ObservingTextFieldDelegate: NSObjectProtocol { @objc public protocol ObservingTextFieldDelegate {
/// Called when the entered text becomes valid based on the validation block /// Called when the entered text becomes valid based on the validation block
@objc optional func isValid(textfield: TextEntryField?) @objc optional func isValid(textfield: TextEntryField?)
/// Called when the entered text becomes invalid based on the validation block /// Called when the entered text becomes invalid based on the validation block
@ -25,7 +25,7 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
open private(set) var textField: TextField = { open private(set) var textField: TextField = {
let textField = TextField(frame: .zero) let textField = TextField()
textField.isAccessibilityElement = true textField.isAccessibilityElement = true
textField.setContentCompressionResistancePriority(.required, for: .vertical) textField.setContentCompressionResistancePriority(.required, for: .vertical)
textField.font = MFStyler.fontForTextField() textField.font = MFStyler.fontForTextField()
@ -85,7 +85,10 @@ import UIKit
/// The text of this TextField. /// The text of this TextField.
open override var text: String? { open override var text: String? {
get { return textField.text } get { return textField.text }
set { textField.text = newValue } set {
textField.text = newValue
(model as? TextEntryFieldModel)?.text = newValue
}
} }
/// Placeholder access for the TextField. /// Placeholder access for the TextField.
@ -169,6 +172,9 @@ import UIKit
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16) textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16)
textFieldTrailingConstraint?.isActive = true textFieldTrailingConstraint?.isActive = true
textField.addTarget(self, action: #selector(startEditing), for: .editingDidBegin)
textField.addTarget(self, action: #selector(dismissFieldInput(_:)), for: .editingDidEnd)
let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing)) let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing))
entryFieldContainer.addGestureRecognizer(tap) entryFieldContainer.addGestureRecognizer(tap)

View File

@ -17,6 +17,7 @@ public enum GraphStyle: String, Codable {
} }
public class CircleProgressModel: MoleculeModelProtocol { public class CircleProgressModel: MoleculeModelProtocol {
public static var identifier: String = "circleProgress" public static var identifier: String = "circleProgress"
public var style: GraphStyle = .unlimited { public var style: GraphStyle = .unlimited {
didSet { didSet {

View File

@ -11,11 +11,15 @@ import Foundation
@objcMembers public class ImageViewModel: MoleculeModelProtocol { @objcMembers public class ImageViewModel: MoleculeModelProtocol {
public static var identifier: String = "image" public static var identifier: String = "image"
public var backgroundColor: Color? public var backgroundColor: Color?
public var image: String public var image: String
public var accessibilityText: String? public var accessibilityText: String?
public var fallbackImage: String? public var fallbackImage: String?
public var imageFormat: String? public var imageFormat: String?
public var width: CGFloat? public var width: CGFloat?
public var height: CGFloat? public var height: CGFloat?
public var contentMode: UIView.ContentMode?
public init(image: String) {
self.image = image
}
} }

View File

@ -220,17 +220,27 @@ public typealias ActionBlock = () -> ()
} }
public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
clauses = [] clauses = []
guard let labelModel = model as? LabelModel else { return }
guard let labelModel = model as? LabelModel else {
text = ""
return
}
attributedText = nil attributedText = nil
originalAttributedString = nil
text = labelModel.text text = labelModel.text
Label.setLabel(self, withHTML: labelModel.html) Label.setLabel(self, withHTML: labelModel.html)
let alignment = LabelAlignment(rawValue: labelModel.textAlignment ?? "") let alignment = LabelAlignment(rawValue: labelModel.textAlignment ?? "")
switch alignment { switch alignment {
case .center: case .center:
textAlignment = .center textAlignment = .center
case .right: case .right:
textAlignment = .right textAlignment = .right
default: default:
textAlignment = .left textAlignment = .left
} }
@ -239,9 +249,11 @@ public typealias ActionBlock = () -> ()
if let backgroundColor = labelModel.backgroundColor { if let backgroundColor = labelModel.backgroundColor {
self.backgroundColor = backgroundColor.uiColor self.backgroundColor = backgroundColor.uiColor
} }
if let accessibilityText = labelModel.accessibilityText { if let accessibilityText = labelModel.accessibilityText {
accessibilityLabel = accessibilityText accessibilityLabel = accessibilityText
} }
if let fontStyle = labelModel.fontStyle { if let fontStyle = labelModel.fontStyle {
MFStyler.styleLabel(self, withStyle: fontStyle) MFStyler.styleLabel(self, withStyle: fontStyle)
MFStyler.styleLabel(self, withStyle: fontStyle, genericScaling: false) MFStyler.styleLabel(self, withStyle: fontStyle, genericScaling: false)
@ -264,19 +276,23 @@ public typealias ActionBlock = () -> ()
if let attributes = labelModel.attributes, let labelText = text { if let attributes = labelModel.attributes, let labelText = text {
let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font.withSize(standardFontSize), NSAttributedString.Key.foregroundColor: textColor as UIColor]) let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font.withSize(standardFontSize), NSAttributedString.Key.foregroundColor: textColor as UIColor])
for attribute in attributes { for attribute in attributes {
let range = NSRange(location: attribute.location, length: attribute.length) let range = NSRange(location: attribute.location, length: attribute.length)
switch attribute { switch attribute {
case _ as LabelAttributeUnderlineModel: case _ as LabelAttributeUnderlineModel:
attributedString.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range) attributedString.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range)
case _ as LabelAttributeStrikeThroughModel: case _ as LabelAttributeStrikeThroughModel:
attributedString.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.thick.rawValue, range: range) attributedString.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.thick.rawValue, range: range)
attributedString.addAttribute(.baselineOffset, value: 0, range: range) attributedString.addAttribute(.baselineOffset, value: 0, range: range)
case let colorAtt as LabelAttributeColorModel: case let colorAtt as LabelAttributeColorModel:
if let colorHex = colorAtt.textColor, !colorHex.isEmpty { if let colorHex = colorAtt.textColor, !colorHex.isEmpty {
attributedString.removeAttribute(.foregroundColor, range: range) attributedString.removeAttribute(.foregroundColor, range: range)
attributedString.addAttribute(.foregroundColor, value: UIColor.mfGet(forHex: colorHex), range: range) attributedString.addAttribute(.foregroundColor, value: UIColor.mfGet(forHex: colorHex), range: range)
} }
case let imageAtt as LabelAttributeImageModel: case let imageAtt as LabelAttributeImageModel:
var fontSize = font.pointSize var fontSize = font.pointSize
if let attributeSize = imageAtt.size { if let attributeSize = imageAtt.size {
@ -293,6 +309,7 @@ public typealias ActionBlock = () -> ()
let mutableString = NSMutableAttributedString() let mutableString = NSMutableAttributedString()
mutableString.append(NSAttributedString(attachment: imageAttachment)) mutableString.append(NSAttributedString(attachment: imageAttachment))
attributedString.insert(mutableString, at: imageAtt.location) attributedString.insert(mutableString, at: imageAtt.location)
case let fontAtt as LabelAttributeFontModel: case let fontAtt as LabelAttributeFontModel:
if let fontStyle = fontAtt.style { if let fontStyle = fontAtt.style {
let styles = MFStyler.styleGetAttributedString("0", withStyle: fontStyle) let styles = MFStyler.styleGetAttributedString("0", withStyle: fontStyle)
@ -320,6 +337,7 @@ public typealias ActionBlock = () -> ()
} }
} }
addActionAttributes(range: range, string: attributedString) addActionAttributes(range: range, string: attributedString)
default: default:
continue continue
} }
@ -381,8 +399,9 @@ public typealias ActionBlock = () -> ()
} }
if let attributes = json?.optionalArrayForKey("attributes"), let labelText = label.text { if let attributes = json?.optionalArrayForKey("attributes"), let labelText = label.text {
let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: mvmLabel?.font.withSize(mvmLabel!.standardFontSize) ?? label.font as UIFont, let attributedString = NSMutableAttributedString(string: labelText,
NSAttributedString.Key.foregroundColor: label.textColor as UIColor]) attributes: [NSAttributedString.Key.font: mvmLabel?.font.withSize(mvmLabel!.standardFontSize) ?? label.font as UIFont,
NSAttributedString.Key.foregroundColor: label.textColor as UIColor])
for case let attribute as [String: Any] in attributes { for case let attribute as [String: Any] in attributes {
guard let attributeType = attribute.optionalStringForKey(KeyType), guard let attributeType = attribute.optionalStringForKey(KeyType),
let location = attribute["location"] as? Int, let location = attribute["location"] as? Int,
@ -733,7 +752,6 @@ extension Label {
/// Applied to existing text. Removes underlines of tappable links and assoated actionable clauses. /// Applied to existing text. Removes underlines of tappable links and assoated actionable clauses.
@objc public func clearActionableClauses() { @objc public func clearActionableClauses() {
guard let attributedText = attributedText else { return } guard let attributedText = attributedText else { return }
let mutableAttributedString = NSMutableAttributedString(attributedString: attributedText) let mutableAttributedString = NSMutableAttributedString(attributedString: attributedText)

View File

@ -9,6 +9,9 @@
import UIKit import UIKit
@objcMembers public class LabelAttributeColorModel: LabelAttributeModel { @objcMembers public class LabelAttributeColorModel: LabelAttributeModel {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
override public class var identifier: String { override public class var identifier: String {
return "color" return "color"
@ -16,14 +19,21 @@ import UIKit
var textColor: String? var textColor: String?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case textColor case textColor
} }
required public init(from decoder: Decoder) throws { //--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
self.textColor = try typeContainer.decodeIfPresent(String.self, forKey: .textColor) textColor = try typeContainer.decodeIfPresent(String.self, forKey: .textColor)
try super.init(from: decoder) try super.init(from: decoder)
} }

View File

@ -8,7 +8,12 @@
import UIKit import UIKit
@objcMembers public class LabelAttributeFontModel: LabelAttributeModel { @objcMembers public class LabelAttributeFontModel: LabelAttributeModel {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
override public class var identifier: String { override public class var identifier: String {
return "font" return "font"
} }
@ -17,17 +22,25 @@ import UIKit
var name: String? var name: String?
var size: CGFloat? var size: CGFloat?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case style case style
case name case name
case size case size
} }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
self.style = try typeContainer.decodeIfPresent(String.self, forKey: .style) style = try typeContainer.decodeIfPresent(String.self, forKey: .style)
self.name = try typeContainer.decodeIfPresent(String.self, forKey: .name) name = try typeContainer.decodeIfPresent(String.self, forKey: .name)
self.size = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .size) size = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .size)
try super.init(from: decoder) try super.init(from: decoder)
} }

View File

@ -9,6 +9,9 @@
import UIKit import UIKit
class LabelAttributeImageModel: LabelAttributeModel { class LabelAttributeImageModel: LabelAttributeModel {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
override public class var identifier: String { override public class var identifier: String {
return "image" return "image"
@ -18,17 +21,25 @@ class LabelAttributeImageModel: LabelAttributeModel {
var name: String? var name: String?
var URL: String? var URL: String?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case size case size
case name case name
case URL case URL
} }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
self.size = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .size) size = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .size)
self.name = try typeContainer.decodeIfPresent(String.self, forKey: .name) name = try typeContainer.decodeIfPresent(String.self, forKey: .name)
self.URL = try typeContainer.decodeIfPresent(String.self, forKey: .URL) URL = try typeContainer.decodeIfPresent(String.self, forKey: .URL)
try super.init(from: decoder) try super.init(from: decoder)
} }

View File

@ -9,6 +9,17 @@
import Foundation import Foundation
@objcMembers open class LabelAttributeModel: Model { @objcMembers open class LabelAttributeModel: Model {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var categoryName: String {
return "\(LabelAttributeModel.self)"
}
public static var categoryCodingKey: String {
return "type"
}
public class var identifier: String { public class var identifier: String {
return "" return ""
@ -18,17 +29,31 @@ import Foundation
var location: Int var location: Int
var length: Int var length: Int
init(_ type: String, _ location: Int, _ length: Int) {
self.type = type
self.location = location
self.length = length
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case type case type
case location case location
case length case length
} }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
self.type = try typeContainer.decode(String.self, forKey: .type) type = try typeContainer.decode(String.self, forKey: .type)
self.location = try typeContainer.decode(Int.self, forKey: .location) location = try typeContainer.decode(Int.self, forKey: .location)
self.length = try typeContainer.decode(Int.self, forKey: .length) length = try typeContainer.decode(Int.self, forKey: .length)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -37,5 +62,4 @@ import Foundation
try container.encode(location, forKey: .location) try container.encode(location, forKey: .location)
try container.encode(length, forKey: .length) try container.encode(length, forKey: .length)
} }
} }

View File

@ -11,9 +11,7 @@ import Foundation
@objcMembers public class LabelModel: MoleculeModelProtocol { @objcMembers public class LabelModel: MoleculeModelProtocol {
public static var identifier: String = "label" public static var identifier: String = "label"
public var moleculeName: String?
public var backgroundColor: Color? public var backgroundColor: Color?
public var text: String public var text: String
public var accessibilityText: String? public var accessibilityText: String?
public var textColor: String? public var textColor: String?
@ -46,21 +44,24 @@ import Foundation
case type case type
} }
public init(text: String) {
self.text = text
}
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
self.moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) text = try typeContainer.decode(String.self, forKey: .text)
self.text = try typeContainer.decode(String.self, forKey: .text) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
self.accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) textColor = try typeContainer.decodeIfPresent(String.self, forKey: .textColor)
self.textColor = try typeContainer.decodeIfPresent(String.self, forKey: .textColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
self.backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) fontStyle = try typeContainer.decodeIfPresent(String.self, forKey: .fontStyle)
self.fontStyle = try typeContainer.decodeIfPresent(String.self, forKey: .fontStyle) fontName = try typeContainer.decodeIfPresent(String.self, forKey: .fontName)
self.fontName = try typeContainer.decodeIfPresent(String.self, forKey: .fontName) fontSize = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .fontSize)
self.fontSize = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .fontSize) textAlignment = try typeContainer.decodeIfPresent(String.self, forKey: .textAlignment)
self.textAlignment = try typeContainer.decodeIfPresent(String.self, forKey: .textAlignment) attributes = try typeContainer.decodeModelsIfPresent(codingKey: .attributes, typeCodingKey: AttributeTypeKey.type) as? [LabelAttributeModel]
self.attributes = try typeContainer.decodeModelsIfPresent(codingKey: .attributes, typeCodingKey: AttributeTypeKey.type) as? [LabelAttributeModel] html = try typeContainer.decodeIfPresent(String.self, forKey: .html)
self.html = try typeContainer.decodeIfPresent(String.self, forKey: .html) hero = try typeContainer.decodeIfPresent(Int.self, forKey: .hero)
self.hero = try typeContainer.decodeIfPresent(Int.self, forKey: .hero) makeWholeViewClickable = try typeContainer.decodeIfPresent(Bool.self, forKey: .makeWholeViewClickable)
self.makeWholeViewClickable = try typeContainer.decodeIfPresent(Bool.self, forKey: .makeWholeViewClickable)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {

View File

@ -232,6 +232,10 @@ import UIKit
imageView.animatedImage = nil imageView.animatedImage = nil
loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage) loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage)
} }
if let contentMode = imageModel.contentMode {
imageView.contentMode = contentMode
}
} }
// MARK: - MVMCoreUIMoleculeViewProtocol functions // MARK: - MVMCoreUIMoleculeViewProtocol functions
@ -357,6 +361,10 @@ import UIKit
loadImage(withName: imageName, format: nil, width: width, height: height, customFallbackImage: nil, completionHandler: completionHandler) loadImage(withName: imageName, format: nil, width: width, height: height, customFallbackImage: nil, completionHandler: completionHandler)
} }
public func loadImage(withName imageName: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?, completionHandler: @escaping MVMCoreGetImageBlock) {
loadImage(withName: imageName, format: nil, width: width, height: height, customFallbackImage: customFallbackImage, completionHandler: completionHandler)
}
public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?) { public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?) {
loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: customFallbackImage, completionHandler: defaultCompletionBlock()) loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: customFallbackImage, completionHandler: defaultCompletionBlock())
} }

View File

@ -28,6 +28,8 @@ import UIKit
private var heroAccessoryCenter: CGPoint? private var heroAccessoryCenter: CGPoint?
private var initialSetupPerformed = false
// MARK: - Styling // MARK: - Styling
open func style(with styleString: String?) { open func style(with styleString: String?) {
guard let styleString = styleString else { guard let styleString = styleString else {
@ -102,12 +104,19 @@ import UIKit
// MARK: - Inits // MARK: - Inits
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier) super.init(style: style, reuseIdentifier: reuseIdentifier)
setupView() initialSetup()
} }
public required init?(coder aDecoder: NSCoder) { public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) super.init(coder: aDecoder)
setupView() initialSetup()
}
public func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
setupView()
}
} }
// MARK: - MFViewProtocol // MARK: - MFViewProtocol
@ -151,10 +160,6 @@ import UIKit
self.listItemModel = model self.listItemModel = model
style(with: model.style) style(with: model.style)
if let backgroundColor = model.backgroundColor {
self.backgroundColor = backgroundColor.uiColor
}
// Add the caret if there is an action and it's not declared hidden. // Add the caret if there is an action and it's not declared hidden.
if !customAccessoryView { if !customAccessoryView {
if let _ = model.action, !(model.hideArrow ?? false) { if let _ = model.action, !(model.hideArrow ?? false) {
@ -169,11 +174,15 @@ import UIKit
addSeparatorsIfNeeded() addSeparatorsIfNeeded()
bottomSeparatorView?.setWithModel(separator, nil, nil) bottomSeparatorView?.setWithModel(separator, nil, nil)
} }
if let moleculeModel = model as? MoleculeModelProtocol,
let backgroundColor = moleculeModel.backgroundColor {
self.backgroundColor = backgroundColor.uiColor
}
} }
open func reset() { open func reset() {
molecule?.reset?() molecule?.reset?()
styleStandard()
backgroundColor = .white backgroundColor = .white
} }

View File

@ -9,41 +9,35 @@
import Foundation import Foundation
extension MFViewController: MoleculeDelegateProtocol { extension MFViewController: MoleculeDelegateProtocol {
public func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? {
guard let name = name else { public func getModuleWithName(_ name: String?) -> [AnyHashable: Any]? {
return nil guard let name = name else { return nil }
}
return loadObject?.modulesJSON?.optionalDictionaryForKey(name) return loadObject?.modulesJSON?.optionalDictionaryForKey(name)
} }
public func getModuleWithName(_ moduleName: String) -> MoleculeModelProtocol? { public func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? {
guard let moduleJSON = loadObject?.modulesJSON?.optionalDictionaryForKey(moduleName), guard let moduleJSON = loadObject?.modulesJSON?.optionalDictionaryForKey(moleculeName),
let moleculeName = moduleJSON.optionalStringForKey("moleculeName"), let moleculeName = moduleJSON.optionalStringForKey("moleculeName"),
let modelType = ModelRegistry.getType(for: moleculeName) as? MoleculeModelProtocol.Type else { let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self)
return nil else { return nil }
}
do { do {
return try modelType.decode(jsonDict: moduleJSON) return try modelType.decode(jsonDict: moduleJSON) as? MoleculeModelProtocol
} catch { } catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)") MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
} }
return nil return nil
} }
@objc public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) { @objc public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) { }
} @objc public func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { }
@objc public func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { @objc public func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { }
// Do nothing
}
@objc public func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// Do nothing
}
} }
public extension MFViewController { public extension MFViewController {
@objc func parsePageJSON() throws { @objc func parsePageJSON() throws { }
}
} }

View File

@ -68,9 +68,8 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController {
open override func updateViewConstraints() { open override func updateViewConstraints() {
super.updateViewConstraints() super.updateViewConstraints()
guard let tableView = tableView else {
return guard let tableView = tableView else { return }
}
let minimumSpace: CGFloat = minimumFillSpace() let minimumSpace: CGFloat = minimumFillSpace()
var currentSpace: CGFloat = 0 var currentSpace: CGFloat = 0
@ -90,9 +89,8 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController {
totalMinimumSpace += minimumSpace totalMinimumSpace += minimumSpace
} }
guard fillTop || fillBottom else { guard fillTop || fillBottom else { return }
return
}
let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace) let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace)
// If the bottom view is outside of the scroll, then only the top view constraint is being used, so we have to double it to account for the bottom constraint not being there when we compare to the new value. // If the bottom view is outside of the scroll, then only the top view constraint is being used, so we have to double it to account for the bottom constraint not being there when we compare to the new value.
@ -168,6 +166,8 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController {
} }
// This extra view is needed because of the wonkiness of apple's table header. Things breaks if using autolayout. // This extra view is needed because of the wonkiness of apple's table header. Things breaks if using autolayout.
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
MVMCoreUIUtility.sizeView(toFit: headerView) MVMCoreUIUtility.sizeView(toFit: headerView)
let tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: MVMCoreUIUtility.getWidth(), height: headerView.frame.height)) let tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: MVMCoreUIUtility.getWidth(), height: headerView.frame.height))
tableHeaderView.addSubview(headerView) tableHeaderView.addSubview(headerView)

View File

@ -0,0 +1,82 @@
//
// ViewController.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 11/5/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers open class ViewController: UIViewController, MVMCoreViewControllerProtocol {
public var pageType: String?
public var loadObject: MVMCoreLoadObject?
public var pageModel: PageModelProtocol?
// MARK: Response handling
public func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool {
pageType = loadObject.pageType
self.loadObject = loadObject
// Parse the model for the page.
do {
try parsePageJSON()
} catch let parsingError {
// Log all parsing errors and fail load.
if let errorObject = MVMCoreErrorObject.createErrorObject(for: parsingError, location: MVMCoreLoadHandler.sharedGlobal()?.errorLocation(forRequest: loadObject)) {
errorObject.messageToDisplay = MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess)
error.pointee = errorObject
}
return false
}
// Verifies all modules needed are loaded.
return MFViewController.verifyRequiredModulesLoaded(for: loadObject, error: error)
}
@objc func parsePageJSON() throws {
}
public class func verifyRequiredModulesLoaded(for loadObject: MVMCoreLoadObject?, error: inout MVMCoreErrorObject?) -> Bool {
guard let pageType = loadObject?.pageType, var modulesRequired = MVMCoreUIViewControllerMappingObject.shared()?.modulesRequired(forPageType: pageType) else { return true }
guard let loadedModules = loadObject?.modulesJSON else { return false }
for case let key as String in Array(loadedModules.keys) {
guard modulesRequired.count > 0 else { break }
if let index = modulesRequired.firstIndex(where: {($0 as? String) == key}) {
modulesRequired.remove(at: index)
}
}
guard modulesRequired.count == 0 else {
if error != nil {
error = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorCritical), messageToLog: modulesRequired.description, code: ErrorCode.requiredModuleNotPresent.rawValue, domain: ErrorDomainNative, location: MVMCoreLoadHandler.sharedGlobal()?.errorLocation(forRequest: loadObject!))
}
return false
}
return true
}
open func setNavigationItem() {
navigationItem.title = pageModel?.screenHeading
navigationItem.accessibilityLabel = pageModel?.screenHeading
}
open func newDataBuildScreen() {
// TODO atomize the navigation item
setNavigationItem()
}
open func initialLoad() {
}
open func updateViews() {
}
override open func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}

View File

@ -9,36 +9,52 @@
import Foundation import Foundation
public extension NSLayoutConstraint { public extension NSLayoutConstraint {
static func pinSubviewsCenter(leftView: UIView, rightView: UIView) {
guard let superView = leftView.superview else { /// Pins the views vertically in the super view, allowing the super to expand depending on the tallest view. Shorter views are aligned center.
return static func pinViewsVerticalExpandableAlignCenter(_ views: [UIView]) {
for view in views {
guard let superView = view.superview else {
return
}
view.centerYAnchor.constraint(equalTo: superView.centerYAnchor).isActive = true
view.topAnchor.constraint(greaterThanOrEqualTo: superView.layoutMarginsGuide.topAnchor).isActive = true
superView.layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor).isActive = true
var constraint = view.topAnchor.constraint(equalTo: superView.layoutMarginsGuide.topAnchor)
constraint.priority = .defaultLow
constraint.isActive = true
constraint = superView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor)
constraint.priority = .defaultLow
constraint.isActive = true
} }
leftView.centerYAnchor.constraint(equalTo: superView.centerYAnchor).isActive = true }
leftView.leftAnchor.constraint(equalTo: superView.layoutMarginsGuide.leftAnchor).isActive = true
leftView.topAnchor.constraint(greaterThanOrEqualTo: superView.layoutMarginsGuide.topAnchor).isActive = true
superView.layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: leftView.bottomAnchor).isActive = true
var constraint = leftView.topAnchor.constraint(equalTo: superView.layoutMarginsGuide.topAnchor) /// Pins the views vertically in the super view, allowing the super to expand depending on the tallest view. Shorter views are aligned top.
constraint.priority = .defaultLow static func pinViewsVerticalExpandableAlignTop(_ views: [UIView]) {
constraint.isActive = true for view in views {
guard let superView = view.superview else {
return
}
view.topAnchor.constraint(equalTo: superView.layoutMarginsGuide.topAnchor).isActive = true
superView.layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor).isActive = true
constraint = superView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: leftView.bottomAnchor) let constraint = superView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor)
constraint.priority = .defaultLow constraint.priority = .defaultLow
constraint.isActive = true constraint.isActive = true
}
}
rightView.leftAnchor.constraint(greaterThanOrEqualTo: leftView.rightAnchor, constant: 16).isActive = true /// Pins a view to the left and a view to the right, flexible space in between. The super can expand depending on the taller view. Shorter views are aligned top if alignTop true, else aligned center.
static func pinViews(leftView: UIView, rightView: UIView, alignTop: Bool) {
rightView.centerYAnchor.constraint(equalTo: superView.centerYAnchor).isActive = true guard let superView = leftView.superview else { return }
superView.layoutMarginsGuide.rightAnchor.constraint(equalTo: rightView.rightAnchor).isActive = true if alignTop {
rightView.topAnchor.constraint(greaterThanOrEqualTo: superView.layoutMarginsGuide.topAnchor).isActive = true pinViewsVerticalExpandableAlignTop([leftView, rightView])
superView.layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: rightView.bottomAnchor).isActive = true } else {
pinViewsVerticalExpandableAlignCenter([leftView, rightView])
constraint = rightView.topAnchor.constraint(equalTo: superView.layoutMarginsGuide.topAnchor) }
constraint.priority = .defaultLow leftView.leadingAnchor.constraint(equalTo: superView.layoutMarginsGuide.leadingAnchor).isActive = true
constraint.isActive = true superView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightView.trailingAnchor).isActive = true
rightView.leftAnchor.constraint(greaterThanOrEqualTo: leftView.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true
constraint = superView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: rightView.bottomAnchor)
constraint.priority = .defaultLow
constraint.isActive = true
} }
} }

View File

@ -12,24 +12,52 @@ public typealias ColorHexTuple = (uiColor: UIColor, hex: String)
extension UIColor { extension UIColor {
//--------------------------------------------------
// MARK: - Convenience Dictionary
//--------------------------------------------------
/// Dictionary to access brand approved colors by name. /// Dictionary to access brand approved colors by name.
public static let names: [String: ColorHexTuple] = ["black": (.mvmBlack, "#000000"), public static let names: [String: ColorHexTuple] = ["black": (.mvmBlack, "#000000"),
"white": (.mvmWhite, "#FFFFFF"), "white": (.mvmWhite, "#FFFFFF"),
"red": (.mvmRed, "#D52B1E"), "red": (.mvmRed, "#D52B1E"),
"orange": (.mvmOrange, "#CC4D0F"), "pink": (.mvmPink, "#D90368"),
"green": (.mvmGreen, "#008631"), "pink33": (.mvmPink33, "#F2ABCD"),
"blue": (.mvmBlue, "#007AB8"), "pink66": (.mvmPink66, "#E6589B"),
"blueGradient": (.mvmBlueGradient, "#007AB8"), "pinkShade1": (.mvmPinkShade1, "#B31C63"),
"pinkShade2": (.mvmPinkShade2, "#830842"),
"purple": (.mvmPurple, "#8C00AC"),
"purple33": (.mvmPurple33, "#D9ABE4"),
"purple66": (.mvmPurple66, "#B356C8"),
"purpleShade1": (.mvmPurpleShade1, "#6C177F"),
"purpleShade2": (.mvmPurpleShade2, "#4A0E58"),
"green": (.mvmGreen, "#008330"),
"green33": (.mvmGreen33, "#ABE4BF"),
"green66": (.mvmGreen66, "#57C880"),
"greenShade1": (.mvmGreenShade1, "#178437"),
"greenShade2": (.mvmGreenShade2, "#0F5B25"),
"orange": (.mvmOrange, "#ED7000"),
"orange66": (.mvmOrange66, "#F3A157"),
"orange33": (.mvmOrange33, "#F9D0AB"),
"orangeShade1": (.mvmOrangeShade1, "#CB5F00"),
"orangeShade2": (.mvmOrangeShade2, "#984700"),
"orangeAA": (.mvmOrangeAA, "#CC4D0F"),
"blue": (.mvmBlue, "#0077B4"),
"blue33": (.mvmBlue33, "#57B1DF"),
"blue66": (.mvmBlue66, "#57B1DF"),
"blueShade1": (.mvmBlueShade1, "#136598"),
"blueShade2": (.mvmBlueShade2, "#0B4467"),
"yellow": (.mvmYellow, "#FFBC3D"), "yellow": (.mvmYellow, "#FFBC3D"),
"yellow33": (.mvmYellow33, "#FFE9BF"),
"yellow66": (.mvmYellow66, "#FFD37F"),
"yellowShade1": (.mvmYellowShade1, "#CC9630"),
"yellowShade2": (.mvmYellowShade2, "#997126"),
"coolGray1": (.mvmCoolGray1, "#F6F6F6"), "coolGray1": (.mvmCoolGray1, "#F6F6F6"),
"coolGray3": (.mvmCoolGray3, "#D8DADA"), "coolGray3": (.mvmCoolGray3, "#D8DADA"),
"coolGray6": (.mvmCoolGray6, "#747676"), "coolGray6": (.mvmCoolGray6, "#747676"),
"coolGray10": (.mvmCoolGray10, "#333333"), "coolGray10": (.mvmCoolGray10, "#333333"),
"vzupGold": (.vzupGold, "#B89B56"), "upGold1": (.vzupGold1, "#F9D542"),
"vzupYellow1": (.vzupYellow1, "#F9D542"), "upGold2": (.vzupGold2, "#F4CA53"),
"vzupYellow2": (.vzupYellow2, "#F4CA53"), "upGold3": (.vzupGold3, "#CC9B2D")]
"vzupYellow3": (.vzupYellow3, "#CC9B2D")]
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Brand // MARK: - Brand
@ -41,24 +69,134 @@ extension UIColor {
/// HEX: #FFFFFF /// HEX: #FFFFFF
public static let mvmWhite = UIColor.white public static let mvmWhite = UIColor.white
//--------------------------------------------------
// MARK: - Red
//--------------------------------------------------
/// HEX: #D52B1E /// HEX: #D52B1E
public static let mvmRed = UIColor.color8Bits(red: 213, green: 43, blue: 30) public static let mvmRed = UIColor.color8Bits(red: 213, green: 43, blue: 30)
//--------------------------------------------------
// MARK: - Pink
//--------------------------------------------------
/// HEX: #D90368
public static let mvmPink = UIColor.color8Bits(red: 217, green: 3, blue: 104)
/// HEX: #F2ABCD
public static let mvmPink33 = UIColor.color8Bits(red: 242, green: 171, blue: 205)
/// HEX: #E6589B
public static let mvmPink66 = UIColor.color8Bits(red: 230, green: 88, blue: 155)
/// HEX: #B31C63
public static let mvmPinkShade1 = UIColor.color8Bits(red: 179, green: 28, blue: 99)
/// HEX: #830842
public static let mvmPinkShade2 = UIColor.color8Bits(red: 131, green: 8, blue: 66)
//--------------------------------------------------
// MARK: - Purple
//--------------------------------------------------
/// HEX: #8C00AC
public static let mvmPurple = UIColor.color8Bits(red: 140, green: 0, blue: 172)
/// HEX: #D9ABE4
public static let mvmPurple33 = UIColor.color8Bits(red: 217, green: 171, blue: 228)
/// HEX: #B356C8
public static let mvmPurple66 = UIColor.color8Bits(red: 179, green: 86, blue: 200)
/// HEX: #6C177F
public static let mvmPurpleShade1 = UIColor.color8Bits(red: 108, green: 23, blue: 127)
/// HEX: #4A0E58
public static let mvmPurpleShade2 = UIColor.color8Bits(red: 74, green: 14, blue: 88)
//--------------------------------------------------
// MARK: - Orange
//--------------------------------------------------
/// HEX: #ED7000
public static let mvmOrange = UIColor.color8Bits(red: 237, green: 112, blue: 0)
/// HEX: #CC4D0F /// HEX: #CC4D0F
public static let mvmOrange = UIColor.color8Bits(red: 204, green: 77, blue: 15) public static let mvmOrangeAA = UIColor.color8Bits(red: 204, green: 77, blue: 15)
/// HEX: #008631 /// HEX: #F9D0AB
public static let mvmGreen = UIColor.color8Bits(red: 0, green: 134, blue: 49) public static let mvmOrange33 = UIColor.color8Bits(red: 249, green: 208, blue: 171)
/// HEX: #007AB8 /// HEX: #F3A157
public static let mvmBlue = UIColor.color8Bits(red: 0, green: 122, blue: 184) public static let mvmOrange66 = UIColor.color8Bits(red: 243, green: 161, blue: 87)
/// HEX: #007AB8 /// HEX: #CB5F00
public static let mvmBlueGradient = UIColor.color8Bits(red: 0, green: 122, blue: 184) public static let mvmOrangeShade1 = UIColor.color8Bits(red: 203, green: 95, blue: 0)
/// HEX: #984700
public static let mvmOrangeShade2 = UIColor.color8Bits(red: 152, green: 71, blue: 0)
//--------------------------------------------------
// MARK: - Green
//--------------------------------------------------
/// HEX: #008330
public static let mvmGreen = UIColor.color8Bits(red: 0, green: 134, blue: 48)
/// HEX: #ABE4BF
public static let mvmGreen33 = UIColor.color8Bits(red: 171, green: 228, blue: 191)
/// HEX: #57C880
public static let mvmGreen66 = UIColor.color8Bits(red: 87, green: 200, blue: 128)
/// HEX: #178437
public static let mvmGreenShade1 = UIColor.color8Bits(red: 23, green: 132, blue: 55)
/// HEX: #0F5B25
public static let mvmGreenShade2 = UIColor.color8Bits(red: 15, green: 91, blue: 37)
//--------------------------------------------------
// MARK: - Blue
//--------------------------------------------------
/// HEX: #0077B4
public static let mvmBlue = UIColor.color8Bits(red: 0, green: 119, blue: 180)
/// HEX: #57B1DF
public static let mvmBlue33 = UIColor.color8Bits(red: 87, green: 177, blue: 223)
/// HEX: #57B1DF
public static let mvmBlue66 = UIColor.color8Bits(red: 87, green: 177, blue: 223)
/// HEX: #136598
public static let mvmBlueShade1 = UIColor.color8Bits(red: 19, green: 101, blue: 152)
/// HEX: #0B4467
public static let mvmBlueShade2 = UIColor.color8Bits(red: 11, green: 68, blue: 103)
//--------------------------------------------------
// MARK: - Yellow
//--------------------------------------------------
/// HEX: #FFBC3D /// HEX: #FFBC3D
public static let mvmYellow = UIColor.color8Bits(red: 255, green: 188, blue: 61) public static let mvmYellow = UIColor.color8Bits(red: 255, green: 188, blue: 61)
/// HEX: #FFE9BF
public static let mvmYellow33 = UIColor.color8Bits(red: 255, green: 233, blue: 191)
/// HEX: #FFD37F
public static let mvmYellow66 = UIColor.color8Bits(red: 255, green: 211, blue: 127)
/// HEX: #CC9630
public static let mvmYellowShade1 = UIColor.color8Bits(red: 204, green: 150, blue: 48)
/// HEX: #997126
public static let mvmYellowShade2 = UIColor.color8Bits(red: 153, green: 113, blue: 38)
//--------------------------------------------------
// MARK: - Gray
//--------------------------------------------------
/// HEX: #F6F6F6 /// HEX: #F6F6F6
public static let mvmCoolGray1 = UIColor.grayscale(rgb: 246) public static let mvmCoolGray1 = UIColor.grayscale(rgb: 246)
@ -75,17 +213,14 @@ extension UIColor {
// MARK: - VZ UP Brand // MARK: - VZ UP Brand
//-------------------------------------------------- //--------------------------------------------------
/// HEX: #B89B56
public static let vzupGold = UIColor.color8Bits(red: 184, green: 155, blue: 68)
/// HEX: #F9D542 /// HEX: #F9D542
public static let vzupYellow1 = UIColor.color8Bits(red: 249, green: 213, blue: 66) public static let vzupGold1 = UIColor.color8Bits(red: 249, green: 213, blue: 66)
/// HEX: #F4CA53 /// HEX: #F4CA53
public static let vzupYellow2 = UIColor.color8Bits(red: 244, green: 202, blue: 83) public static let vzupGold2 = UIColor.color8Bits(red: 244, green: 202, blue: 83)
/// HEX: #CC9B2D /// HEX: #CC9B2D
public static let vzupYellow3 = UIColor.color8Bits(red: 204, green: 155, blue: 45) public static let vzupGold3 = UIColor.color8Bits(red: 204, green: 155, blue: 45)
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Functions // MARK: - Functions

View File

@ -21,6 +21,7 @@
+ (nonnull UIColor *)mfLightSilver; + (nonnull UIColor *)mfLightSilver;
+ (nonnull UIColor *)mfDarkSilver; + (nonnull UIColor *)mfDarkSilver;
+ (nonnull UIColor *)mfTomatoRed; + (nonnull UIColor *)mfTomatoRed;
+ (nonnull UIColor *)mvmOrange;
+ (nonnull UIColor *)mfPumpkinColor; + (nonnull UIColor *)mfPumpkinColor;
+ (nonnull UIColor *)mfShamrock; + (nonnull UIColor *)mfShamrock;
+ (nonnull UIColor *)mfCerulean; + (nonnull UIColor *)mfCerulean;

View File

@ -37,7 +37,6 @@
return [UIColor mfColor8bitsWithRed:198 green:197 blue:197 alpha:1.0]; return [UIColor mfColor8bitsWithRed:198 green:197 blue:197 alpha:1.0];
} }
+ (nonnull UIColor *)mfPrimaryButtonHighlightBlackColor { + (nonnull UIColor *)mfPrimaryButtonHighlightBlackColor {
return [UIColor mfColor8bitsWithRed:51 green:51 blue:51 alpha:1.0]; return [UIColor mfColor8bitsWithRed:51 green:51 blue:51 alpha:1.0];
} }
@ -54,6 +53,10 @@
return [UIColor mfColor8bitsWithRed:204 green:77 blue:15 alpha:1.0]; return [UIColor mfColor8bitsWithRed:204 green:77 blue:15 alpha:1.0];
} }
+ (nonnull UIColor *)mvmOrange {
return [UIColor mfColor8bitsWithRed:237 green:112 blue:0 alpha:1.0];
}
+ (nonnull UIColor *)mfShamrock { + (nonnull UIColor *)mfShamrock {
return [UIColor mfColor8bitsWithRed:0 green:134 blue:49 alpha:1.0]; return [UIColor mfColor8bitsWithRed:0 green:134 blue:49 alpha:1.0];
} }

View File

@ -0,0 +1,98 @@
//
// UIContentMode+Extension.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 2/17/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
enum ContentModeError: Error {
case notAContentMode
}
extension UIView.ContentMode: RawRepresentable {
init?(rawValue: String) {
switch rawValue {
case "scaleToFill":
self = .scaleToFill
case "scaleAspectFit":
self = .scaleAspectFit
case "scaleAspectFill":
self = .scaleAspectFill
case "redraw":
self = .redraw
case "center":
self = .center
case "top":
self = .top
case "bottom":
self = .bottom
case "left":
self = .left
case "right":
self = .right
case "topLeft":
self = .topLeft
case "topRight":
self = .topRight
case "bottomLeft":
self = .bottomLeft
case "bottomRight":
self = .bottomRight
default:
return nil
}
}
var rawValueString: String {
switch self {
case .scaleToFill:
return "scaleToFill"
case .scaleAspectFit:
return "scaleAspectFit"
case .scaleAspectFill:
return "scaleAspectFill"
case .redraw:
return "redraw"
case .center:
return "center"
case .top:
return "top"
case .bottom:
return "bottom"
case .left:
return "left"
case .right:
return "right"
case .topLeft:
return "topLeft"
case .topRight:
return "topRight"
case .bottomLeft:
return "bottomLeft"
case .bottomRight:
return "bottomRight"
@unknown default:
return ""
}
}
}
extension UIView.ContentMode: Codable {
public init(from decoder: Decoder) throws {
let typeContainer = try decoder.singleValueContainer()
let string = try typeContainer.decode(String.self)
guard let mode = UIView.ContentMode(rawValue: string) else {
throw ContentModeError.notAContentMode
}
self = mode
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(rawValueString)
}
}

View File

@ -48,7 +48,8 @@ public class ContainerModel: ContainerModelProtocol, Codable {
try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: horizontalAlignment), forKey: .horizontalAlignment) try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: horizontalAlignment), forKey: .horizontalAlignment)
try container.encodeIfPresent(useHorizontalMargins, forKey: .useHorizontalMargins) try container.encodeIfPresent(useHorizontalMargins, forKey: .useHorizontalMargins)
try container.encodeIfPresent(useVerticalMargins, forKey: .useVerticalMargins) try container.encodeIfPresent(useVerticalMargins, forKey: .useVerticalMargins)
try container.encodeIfPresent(topMarginPadding, forKey: .topMarginPadding) // TODO: can add this back once we have type erasures.
try container.encodeIfPresent(bottomMarginPadding, forKey: .bottomMarginPadding) //try container.encodeIfPresent(topMarginPadding, forKey: .topMarginPadding)
//try container.encodeIfPresent(bottomMarginPadding, forKey: .bottomMarginPadding)
} }
} }

View File

@ -49,7 +49,7 @@ public final class Color: Codable {
// MARK: - Class Initializers // MARK: - Class Initializers
//-------------------------------------------------- //--------------------------------------------------
init(uiColor: UIColor) { public init(uiColor: UIColor) {
self.uiColor = uiColor self.uiColor = uiColor
hex = UIColor.hexString(for: uiColor) ?? "" hex = UIColor.hexString(for: uiColor) ?? ""
determineRGBA() determineRGBA()

View File

@ -8,7 +8,9 @@
import Foundation import Foundation
extension KeyedDecodingContainer where Key : CodingKey {
extension KeyedDecodingContainer where Key: CodingKey {
private enum TypeCodingKey: String, CodingKey { private enum TypeCodingKey: String, CodingKey {
case moleculeName case moleculeName
} }

View File

@ -8,7 +8,8 @@
import Foundation import Foundation
public protocol CarouselItemModelProtocol: ContainerModelProtocol, MoleculeModelProtocol { public protocol CarouselItemModelProtocol: ContainerModelProtocol, MoleculeModelProtocol {
var peakingUI: Bool? {get} var peakingUI: Bool? { get }
var peakingArrowColor: Color? {get} var peakingArrowColor: Color? { get }
} }

View File

@ -8,6 +8,7 @@
import Foundation import Foundation
public protocol CarouselPagingModelProtocol: MoleculeModelProtocol { public protocol CarouselPagingModelProtocol: MoleculeModelProtocol {
var position: Float? {get} var position: Float? { get }
} }

View File

@ -8,6 +8,7 @@
import Foundation import Foundation
public protocol ContainerModelProtocol { public protocol ContainerModelProtocol {
var horizontalAlignment: UIStackView.Alignment? { get set } var horizontalAlignment: UIStackView.Alignment? { get set }
var verticalAlignment: UIStackView.Alignment? { get set } var verticalAlignment: UIStackView.Alignment? { get set }

View File

@ -8,6 +8,7 @@
import Foundation import Foundation
public protocol EnableableModelProtocol { public protocol EnableableModelProtocol {
var enabled: Bool { get set } var enabled: Bool { get set }
} }

View File

@ -8,6 +8,7 @@
import Foundation import Foundation
public protocol FormModelProtocol: Model { public protocol FormModelProtocol: Model {
var required: Bool? { get } var required: Bool? { get }
var fieldKey: String? { get } var fieldKey: String? { get }

View File

@ -8,7 +8,8 @@
import Foundation import Foundation
public protocol ListItemModelProtocol: ContainerModelProtocol, MoleculeModelProtocol {
public protocol ListItemModelProtocol: ContainerModelProtocol {
var line: LineModel? { get set } var line: LineModel? { get set }
var action: ActionModelProtocol? { get set } var action: ActionModelProtocol? { get set }
var hideArrow: Bool? { get set } var hideArrow: Bool? { get set }
@ -16,20 +17,15 @@ public protocol ListItemModelProtocol: ContainerModelProtocol, MoleculeModelProt
} }
// Not a strict requirement. // Not a strict requirement.
extension ListItemModelProtocol { public extension ListItemModelProtocol {
public var action: ActionModelProtocol? {
get { var action: ActionModelProtocol? {
return nil get { return nil }
} set { }
set {
}
} }
public var style: String? { var style: String? {
get { get { return nil }
return nil set { }
}
set {
}
} }
} }

View File

@ -1,12 +1,22 @@
import Foundation import Foundation
public protocol MoleculeModelProtocol: Model { public protocol MoleculeModelProtocol: Model {
var moleculeName: String? { get } var moleculeName: String? { get }
var backgroundColor: Color? { get set} var backgroundColor: Color? { get set}
} }
extension MoleculeModelProtocol { public extension MoleculeModelProtocol {
public var moleculeName: String? {
var moleculeName: String? {
get { return Self.identifier } get { return Self.identifier }
} }
static var categoryName: String {
return "\(MoleculeModelProtocol.self)"
}
static var categoryCodingKey: String {
return "moleculeName"
}
} }

View File

@ -8,7 +8,8 @@
import Foundation import Foundation
public protocol PageModelProtocol: Model {
public protocol PageModelProtocol {
var pageType: String { get set } var pageType: String { get set }
var screenHeading: String? { get set } var screenHeading: String? { get set }
var isAtomicTabs: Bool? { get set } var isAtomicTabs: Bool? { get set }

View File

@ -8,12 +8,22 @@
import Foundation import Foundation
public protocol TemplateModelProtocol: PageModelProtocol {
public protocol TemplateModelProtocol: PageModelProtocol, Model {
var template: String { get } var template: String { get }
} }
extension TemplateModelProtocol { public extension TemplateModelProtocol {
public var template: String {
var template: String {
get { return Self.identifier } get { return Self.identifier }
} }
static var categoryCodingKey: String {
return "template"
}
static var categoryName: String {
return "\(TemplateModelProtocol.self)"
}
} }

View File

@ -0,0 +1,71 @@
//
// ListLeftVariableIconWithRightCaret.swift
// MVMCoreUI
//
// Created by Kruthika KP on 03/02/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
import UIKit
@objcMembers public class ListLeftVariableIconWithRightCaret: TableViewCell {
//-----------------------------------------------------
// MARK: - Outlets
//-------------------------------------------------------
let leftImage = MFLoadImageView(pinnedEdges: .all)
let leftLabel = Label.commonLabelB2(true)
let rightLabel = Label.commonLabelB2(true)
let stack = Stack<StackModel>(frame: .zero)
//-----------------------------------------------------
// MARK: - View Lifecycle
//-------------------------------------------------------
open override func updateView(_ size: CGFloat) {
super.updateView(size)
stack.updateView(size)
}
override open func setupView() {
super.setupView()
stack.translatesAutoresizingMaskIntoConstraints = false
stack.stackItems = [StackItem(andContain: leftImage),StackItem(andContain: leftLabel),StackItem(andContain: rightLabel)]
contentView.addSubview(stack)
containerHelper.constrainView(stack)
leftLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal)
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal)
}
//----------------------------------------------------
// MARK: - Molecule
//------------------------------------------------------
override open func reset() {
super.reset()
stack.reset()
}
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? ListLeftVariableIconWithRightCaretModel else { return}
leftImage.setWithModel(model.image, delegateObject, additionalData)
leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData)
rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData)
// Create a stack model to use for the internal stack and set the alignment of labels
let leftImage = StackItemModel()
leftImage.horizontalAlignment = .fill
let leftLabel = StackItemModel()
leftLabel.horizontalAlignment = .fill
let rightLabel = StackItemModel()
rightLabel.horizontalAlignment = .trailing
let stackModel = StackModel(molecules: [leftImage,leftLabel,rightLabel])
stackModel.axis = .horizontal
stack.model = stackModel
stack.restack()
}
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 90
}
}

View File

@ -0,0 +1,56 @@
//
// ListLeftVariableIconWithRightCaretModel.swift
// MVMCoreUI
//
// Created by Kruthika KP on 03/02/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class ListLeftVariableIconWithRightCaretModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "listLVImg"
public var image: ImageViewModel
public var leftLabel: LabelModel
public var rightLabel: LabelModel
override public func setDefaults() {
super.setDefaults()
if image.height == nil {
image.height = 30.0
}
}
public init(image: ImageViewModel, leftLabel: LabelModel, rightLabel: LabelModel) {
self.image = image
self.leftLabel = leftLabel
self.rightLabel = rightLabel
super.init()
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case leftLabel
case rightLabel
case image
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
image = try typeContainer.decode(ImageViewModel.self, forKey: .image)
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(leftLabel, forKey: .leftLabel)
try container.encode(rightLabel, forKey: .rightLabel)
try container.encode(image, forKey: .image)
}
}

View File

@ -0,0 +1,64 @@
//
// ThreeColumnPlanDataDividerList.swift
// MVMCoreUI
//
// Created by Acharya, Subhankar on 04/02/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class ListThreeColumnPlanDataDivider: TableViewCell {
let leftHeadlineBody = HeadlineBody(frame: .zero)
let centerHeadLineBody = HeadlineBody(frame: .zero)
let rightHeadLineBody = HeadlineBody(frame: .zero)
let stack = Stack<StackModel>(frame: .zero)
// MARK: - MFViewProtocol
open override func updateView(_ size: CGFloat) {
super.updateView(size)
stack.updateView(size)
}
open override func setupView() {
super.setupView()
//using stackItems to align the three headlineBody
stack.translatesAutoresizingMaskIntoConstraints = false
stack.stackItems = [StackItem(andContain: leftHeadlineBody),StackItem(andContain: centerHeadLineBody),StackItem(andContain: rightHeadLineBody)]
contentView.addSubview(stack)
containerHelper.constrainView(stack)
}
// MARK: - MVMCoreUIMoleculeViewProtocol
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? ListThreeColumnPlanDataDividerModel else { return }
leftHeadlineBody.setWithModel(model.leftHeadlineBody, delegateObject, additionalData)
centerHeadLineBody.setWithModel(model.centerHeadlineBody, delegateObject, additionalData)
rightHeadLineBody.setWithModel(model.rightHeadlineBody, delegateObject, additionalData)
// Create a stack model to use for the internal stack and set the alignment of models
let leftHeadlineBodyAlignment = StackItemModel(percent: 33)
leftHeadlineBodyAlignment.horizontalAlignment = .leading
let centerHeadLineBodyAlignment = StackItemModel(percent: 34)
centerHeadLineBodyAlignment.horizontalAlignment = .center
let rightHeadLineBodyAlignment = StackItemModel(percent: 33)
rightHeadLineBodyAlignment.horizontalAlignment = .trailing
let stackModel = StackModel(molecules: [leftHeadlineBodyAlignment,centerHeadLineBodyAlignment,rightHeadLineBodyAlignment])
stackModel.axis = .horizontal
stack.model = stackModel
stack.restack()
}
open override func reset() {
super.reset()
stack.reset()
}
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return 121
}
}

View File

@ -0,0 +1,55 @@
//
// ThreeColumnPlanDataDividerListModel.swift
// MVMCoreUI
//
// Created by Acharya, Subhankar on 04/02/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import UIKit
public class ListThreeColumnPlanDataDividerModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "list3CHBDiv"
public var leftHeadlineBody: HeadlineBodyModel
public var centerHeadlineBody: HeadlineBodyModel
public var rightHeadlineBody: HeadlineBodyModel
public init(leftHeadlineBody: HeadlineBodyModel, centerHeadlineBody:HeadlineBodyModel, rightHeadlineBody: HeadlineBodyModel) {
self.leftHeadlineBody = leftHeadlineBody
self.centerHeadlineBody = centerHeadlineBody
self.rightHeadlineBody = rightHeadlineBody
super.init()
setDefaults()
}
/// Defaults to set
override public func setDefaults() {
super.setDefaults()
style = "tallDivider"
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case leftHeadlineBody
case centerHeadlineBody
case rightHeadlineBody
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
leftHeadlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .leftHeadlineBody)
centerHeadlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .centerHeadlineBody)
rightHeadlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .rightHeadlineBody)
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(leftHeadlineBody, forKey: .leftHeadlineBody)
try container.encode(centerHeadlineBody, forKey: .centerHeadlineBody)
try container.encode(rightHeadlineBody, forKey: .rightHeadlineBody)
}
}

View File

@ -10,13 +10,14 @@ import UIKit
@objcMembers open class ImageHeadlineBody: View { @objcMembers open class ImageHeadlineBody: View {
let headlineBody = HeadlineBody(frame: .zero) let headlineBody = HeadlineBody(frame: .zero)
let imageView = MFLoadImageView() let imageView = MFLoadImageView(pinnedEdges: .all)
var constraintBetweenImageLabelsConstant: CGFloat = 16 var constraintBetweenImageLabelsConstant: CGFloat = 16
var constraintBetweenImageLabels: NSLayoutConstraint? var constraintBetweenImageLabels: NSLayoutConstraint?
// MARK: - MFViewProtocol // MARK: - MFViewProtocol
open override func setupView() { open override func setupView() {
super.setupView()
guard subviews.count == 0 else { guard subviews.count == 0 else {
return return
} }
@ -26,23 +27,9 @@ import UIKit
addSubview(headlineBody) addSubview(headlineBody)
addSubview(imageView) addSubview(imageView)
headlineBody.topAnchor.constraint(equalTo: topAnchor).isActive = true NSLayoutConstraint.pinViewsVerticalExpandableAlignCenter([imageView, headlineBody])
rightAnchor.constraint(equalTo: headlineBody.rightAnchor).isActive = true rightAnchor.constraint(equalTo: headlineBody.rightAnchor).isActive = true
bottomAnchor.constraint(greaterThanOrEqualTo: headlineBody.bottomAnchor).isActive = true
var constraint = bottomAnchor.constraint(equalTo: headlineBody.bottomAnchor)
constraint.priority = .defaultLow
constraint.isActive = true
imageView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
imageView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true imageView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
imageView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true
bottomAnchor.constraint(greaterThanOrEqualTo: imageView.bottomAnchor).isActive = true
constraint = bottomAnchor.constraint(equalTo: imageView.bottomAnchor)
constraint.priority = UILayoutPriority(rawValue: 200)
constraint.isActive = true
constraint = imageView.topAnchor.constraint(equalTo: topAnchor)
constraint.priority = UILayoutPriority(rawValue: 200)
constraint.isActive = true
constraintBetweenImageLabels = headlineBody.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: constraintBetweenImageLabelsConstant) constraintBetweenImageLabels = headlineBody.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: constraintBetweenImageLabelsConstant)
constraintBetweenImageLabels?.isActive = true constraintBetweenImageLabels?.isActive = true

View File

@ -8,11 +8,11 @@
import UIKit import UIKit
@objcMembers open class TwoButtonView: ViewConstrainingView { @objcMembers open class TwoButtonView: View, MVMCoreUIViewConstrainingProtocol {
open var primaryButton: PrimaryButton? = PrimaryButton.button() open var primaryButton: PillButton = PillButton()
open var secondaryButton: PrimaryButton? = PrimaryButton.button() open var secondaryButton: PillButton = PillButton()
open var viewForButtons: UIView? private var stack = UIStackView()
public var heightConstraint: NSLayoutConstraint? private var equalWidthConstraint: NSLayoutConstraint?
public init() { public init() {
super.init(frame: .zero) super.init(frame: .zero)
@ -26,289 +26,100 @@ import UIKit
super.init(frame: frame) super.init(frame: frame)
} }
public func setDefaultCustom() { public func setDefault() {
primaryButton?.setAsStandardCustom() primaryButton.stylePrimary()
secondaryButton?.setAsSecondaryCustom() secondaryButton.styleSecondary()
} }
// MARK: - MVMCoreViewProtocol // MARK: - MVMCoreViewProtocol
open override func updateView(_ size: CGFloat) { open override func updateView(_ size: CGFloat) {
super.updateView(size) super.updateView(size)
MVMCoreDispatchUtility.performBlock(onMainThread: { self.primaryButton.updateView(size)
self.primaryButton?.updateView(size) self.secondaryButton.updateView(size)
self.secondaryButton?.updateView(size)
})
} }
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
setupWithTwoButtons()
secondaryButton?.bordered = true stack.translatesAutoresizingMaskIntoConstraints = false
addSubview(stack)
stack.addArrangedSubview(secondaryButton)
stack.addArrangedSubview(primaryButton)
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
stack.axis = .horizontal
stack.spacing = 10
equalWidthConstraint = secondaryButton.widthAnchor.constraint(equalTo: primaryButton.widthAnchor, multiplier: 1)
equalWidthConstraint?.isActive = true
}
// MARK: - Stack Manipulation
public func showPrimaryButton() {
if !stack.arrangedSubviews.contains(primaryButton) {
stack.addArrangedSubview(primaryButton)
primaryButton.isHidden = false
}
if secondaryButton.superview != nil {
equalWidthConstraint?.isActive = true
}
}
public func showSecondaryButton() {
if !stack.arrangedSubviews.contains(secondaryButton) {
stack.insertArrangedSubview(secondaryButton, at: 0)
secondaryButton.isHidden = false
}
if primaryButton.superview != nil {
equalWidthConstraint?.isActive = true
}
}
public func hidePrimaryButton() {
if primaryButton.superview != nil {
stack.removeArrangedSubview(primaryButton)
primaryButton.isHidden = true
}
equalWidthConstraint?.isActive = false
}
public func hideSecondaryButton() {
if secondaryButton.superview != nil {
stack.removeArrangedSubview(secondaryButton)
secondaryButton.isHidden = true
}
equalWidthConstraint?.isActive = false
} }
// MARK: - MVMCoreUIMoleculeViewProtocol // MARK: - MVMCoreUIMoleculeViewProtocol
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
let primaryButtonMap = json?.optionalDictionaryForKey("primaryButton")
let secondaryButtonMap = json?.optionalDictionaryForKey("secondaryButton")
set(primaryButtonJSON: primaryButtonMap, secondaryButtonJSON: secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
}
open override func reset() { open override func reset() {
super.reset() super.reset()
primaryButton?.setAsStandardCustom() setDefault()
secondaryButton?.setAsSecondaryCustom()
} }
// MARK: - Constraining // MARK: - MVMCoreUIViewConstrainingProtocol
func createPrimaryButton() { open func horizontalAlignment() -> UIStackView.Alignment {
if primaryButton == nil {
primaryButton = PrimaryButton.button()
}
}
func createSecondaryButton() {
if secondaryButton == nil {
secondaryButton = PrimaryButton.button()
secondaryButton?.bordered = true
}
}
func removeButtons() {
viewForButtons?.removeFromSuperview()
primaryButton?.removeFromSuperview()
secondaryButton?.removeFromSuperview()
viewForButtons = nil
secondaryButton = nil
primaryButton = nil
}
open func setupConstraintsForViewWithButtons() {
guard let viewForButtons = viewForButtons,
let primaryButton = primaryButton,
let secondaryButton = secondaryButton
else { return }
viewForButtons.addSubview(primaryButton)
viewForButtons.addSubview(secondaryButton)
secondaryButton.widthAnchor.constraint(equalTo: primaryButton.widthAnchor, multiplier: 1).isActive = true
NSLayoutConstraint.constraintPinSubview(secondaryButton, pinTop: true, pinBottom: true, pinLeft: true, pinRight: false)
NSLayoutConstraint.constraintPinSubview(primaryButton, pinTop: true, pinBottom: true, pinLeft: false, pinRight: true)
let constraint = primaryButton.leadingAnchor.constraint(equalTo: secondaryButton.trailingAnchor, constant: 10)
constraint.priority = UILayoutPriority(900)
constraint.isActive = true
}
func setupWithTwoButtons() {
guard viewForButtons == nil else {
return
}
let viewForButtons = MVMCoreUICommonViewsUtility.commonView()
addSubview(viewForButtons)
self.viewForButtons = viewForButtons
pinView(toSuperView: viewForButtons)
alignCenterHorizontal()
createPrimaryButton()
createSecondaryButton()
setupConstraintsForViewWithButtons()
}
open func setupWithPrimaryButton() {
guard primaryButton == nil && secondaryButton == nil else {
return
}
createPrimaryButton()
if let primaryButton = primaryButton {
addSubview(primaryButton)
pinView(toSuperView: primaryButton)
alignCenterHorizontal()
}
}
open func setupWithSecondaryButton() {
guard secondaryButton == nil && primaryButton == nil else {
return
}
createSecondaryButton()
if let secondaryButton = secondaryButton {
addSubview(secondaryButton)
pinView(toSuperView: secondaryButton)
alignCenterHorizontal()
}
}
/// Legacy
func setupUI(withPrimaryButtonMap primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?) {
setupUI(primaryButtonShowing: primaryButtonMap != nil, secondaryButtonShowing: secondaryButtonMap != nil)
}
func setupUI(primaryButtonShowing: Bool, secondaryButtonShowing: Bool) {
if primaryButtonShowing, secondaryButtonShowing {
heightConstraint?.isActive = false
if primaryButton == nil || secondaryButton == nil {
removeButtons()
setupWithTwoButtons()
}
} else if primaryButtonShowing {
heightConstraint?.isActive = false
if primaryButton == nil || secondaryButton != nil {
removeButtons()
setupWithPrimaryButton()
}
} else if secondaryButtonShowing {
heightConstraint?.isActive = false
if secondaryButton == nil || primaryButton != nil {
removeButtons()
setupWithSecondaryButton()
}
} else {
removeButtons()
if heightConstraint == nil {
heightConstraint = heightAnchor.constraint(equalToConstant: 0)
heightConstraint?.isActive = true
}
}
}
open func set(primaryButtonJSON: [AnyHashable: Any]?, secondaryButtonJSON: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
setupUI(withPrimaryButtonMap: primaryButtonJSON, secondaryButtonMap: secondaryButtonJSON)
setDefaultCustom()
primaryButton?.setWithJSON(primaryButtonJSON, delegateObject: delegateObject, additionalData: additionalData)
secondaryButton?.setWithJSON(secondaryButtonJSON, delegateObject: delegateObject, additionalData: additionalData)
}
// MARK: - Legacy
public convenience init(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
self.init()
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
}
public convenience init(buttonSmall small: Bool, buttonMap: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: AnyHashable]?) {
self.init()
setup(withButtonMap: buttonMap, delegateObject: delegateObject, additionalData: additionalData)
primaryButton?.setAsSmall(small)
secondaryButton?.setAsSmall(small)
}
public convenience init(buttonSmall small: Bool, enabled: Bool) {
self.init()
removeButtons()
setupWithPrimaryButton()
primaryButton?.setAsSmall(small)
primaryButton?.isEnabled = enabled
}
open func setup(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
setupUI(withPrimaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap)
if primaryButtonMap != nil, secondaryButtonMap != nil {
primaryButton?.setWithActionMap(primaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
secondaryButton?.setWithActionMap(secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
} else if primaryButtonMap != nil {
primaryButton?.setWithActionMap(primaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
primaryButton?.bordered = false
} else if secondaryButtonMap != nil {
secondaryButton?.setWithActionMap(secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
secondaryButton?.bordered = true
}
}
open func setup(withButtonMap buttonMap: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
let secondaryButtonMap = buttonMap?.optionalDictionaryForKey(KeySecondaryButton)
let primaryButtonMap = buttonMap?.optionalDictionaryForKey(KeyPrimaryButton)
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
}
public func hideLeftButton() {
guard let secondaryButton = secondaryButton, !secondaryButton.isHidden else {
return
}
secondaryButton.isHidden = true
if let primaryButton = primaryButton {
primaryButton.removeFromSuperview()
viewForButtons?.addSubview(primaryButton)
NSLayoutConstraint.constraintPinSubview(toSuperview: primaryButton)
}
}
public func hideRightButton() {
guard let primaryButton = primaryButton, !primaryButton.isHidden else {
return
}
primaryButton.isHidden = true
if let secondaryButton = secondaryButton {
secondaryButton.removeFromSuperview()
viewForButtons?.addSubview(secondaryButton)
NSLayoutConstraint.constraintPinSubview(toSuperview: secondaryButton)
}
}
public func showBothButtons() {
primaryButton?.isHidden = false
secondaryButton?.isHidden = false
if let primaryButton = primaryButton, let secondaryButton = secondaryButton {
primaryButton.removeFromSuperview()
secondaryButton.removeFromSuperview()
setupConstraintsForViewWithButtons()
}
}
public func hideBothButtons() {
primaryButton?.isHidden = true
secondaryButton?.isHidden = true
}
override open func horizontalAlignment() -> UIStackView.Alignment {
return .center return .center
} }
}
// MARK: - Deprecate // MARK: - ModelMoleculeViewProtocol
extension TwoButtonView { public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
@available(*, deprecated) guard let model = molecule as? TwoButtonViewModel else { return 0 }
open func setup(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) { return PillButton.estimatedHeight(forRow: model.primaryButton ?? model.secondaryButton, delegateObject: delegateObject)
setupUI(withPrimaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap) }
if primaryButtonMap != nil, secondaryButtonMap != nil {
primaryButton?.setWithActionMap(primaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol) public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
secondaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol) super.setWithModel(model, delegateObject, additionalData)
} else if primaryButtonMap != nil { guard let model = model as? TwoButtonViewModel else { return }
primaryButton?.setWithActionMap(primaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol) if let secondaryModel = model.secondaryButton {
primaryButton?.bordered = false showSecondaryButton()
} else if secondaryButtonMap != nil { secondaryButton.setWithModel(secondaryModel, delegateObject, additionalData)
secondaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol) } else {
secondaryButton?.bordered = true hideSecondaryButton()
}
if let primaryModel = model.primaryButton {
showPrimaryButton()
primaryButton.setWithModel(primaryModel, delegateObject, additionalData)
} else {
hidePrimaryButton()
} }
} }
@available(*, deprecated)
open func setup(withButtonMap buttonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) {
let secondaryButtonMap = buttonMap?.optionalDictionaryForKey(KeySecondaryButton)
let primaryButtonMap = buttonMap?.optionalDictionaryForKey(KeyPrimaryButton)
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
}
@available(*, deprecated)
public convenience init(buttonSmall small: Bool, buttonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: AnyHashable]?, buttonDelegate: Any?) {
self.init()
setup(withButtonMap: buttonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
primaryButton?.setAsSmall(small)
secondaryButton?.setAsSmall(small)
}
@available(*, deprecated)
public convenience init(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) {
self.init()
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
}
}
extension TwoButtonView: ModelMoleculeViewProtocol {
public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? TwoButtonViewModel else { return }
setupUI(primaryButtonShowing: model.primaryButton != nil, secondaryButtonShowing: model.secondaryButton != nil)
setDefaultCustom()
primaryButton?.setWithModel(model.primaryButton, delegateObject, additionalData)
secondaryButton?.setWithModel(model.secondaryButton, delegateObject, additionalData)
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
}
} }

View File

@ -8,9 +8,40 @@
import UIKit import UIKit
public struct TwoButtonViewModel: MoleculeModelProtocol { public class TwoButtonViewModel: MoleculeModelProtocol {
public static var identifier: String = "twoButtonView" public static var identifier: String = "twoButtonView"
public var backgroundColor: Color? public var backgroundColor: Color?
public var primaryButton: ButtonModel? public var primaryButton: ButtonModel?
public var secondaryButton: ButtonModel? public var secondaryButton: ButtonModel?
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case primaryButton
case secondaryButton
}
public init(_ primaryButton: ButtonModel?, _ secondaryButton: ButtonModel?) {
self.primaryButton = primaryButton
self.secondaryButton = secondaryButton
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
primaryButton = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .primaryButton)
secondaryButton = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .secondaryButton)
// Default value
if secondaryButton?.style == nil {
secondaryButton?.style = .secondary
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(primaryButton, forKey: .primaryButton)
try container.encodeIfPresent(secondaryButton, forKey: .secondaryButton)
}
} }

View File

@ -8,28 +8,31 @@
import UIKit import UIKit
class AccordionListItemModel: MoleculeContainerModel, ListItemModelProtocol { class AccordionListItemModel: MoleculeListItemModel {
public static var identifier: String = "accordionListItem" override public class var identifier: String {
public var molecules: [ListItemModelProtocol] return "accordionListItem"
public var backgroundColor: Color? }
public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]
public var hideLineWhenExpanded: Bool = false public var hideLineWhenExpanded: Bool = false
public var hideArrow: Bool? = true
public var line: LineModel?
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case molecules case molecules
case backgroundColor case molecule
case hideLineWhenExpanded case hideLineWhenExpanded
case hideArrow }
case line
public override func setDefaults() {
super.setDefaults()
hideArrow = true
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decodeMolecules(codingKey: .molecules) as! [ListItemModelProtocol] guard let molecules = try typeContainer.decodeMolecules(codingKey: .molecules) as? [ListItemModelProtocol & MoleculeModelProtocol] else {
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) throw DecodingError.typeMismatch([ListItemModelProtocol & MoleculeModelProtocol].self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Casting failed"))
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) }
self.molecules = molecules
if let hideLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideLineWhenExpanded) { if let hideLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideLineWhenExpanded) {
hideLineWhenExpanded = hideLine hideLineWhenExpanded = hideLine
} }
@ -41,8 +44,6 @@ class AccordionListItemModel: MoleculeContainerModel, ListItemModelProtocol {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModels(molecules, forKey: .molecules) try container.encodeModels(molecules, forKey: .molecules)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(hideLineWhenExpanded, forKey: .hideLineWhenExpanded) try container.encodeIfPresent(hideLineWhenExpanded, forKey: .hideLineWhenExpanded)
try container.encodeIfPresent(line, forKey: .line)
} }
} }

View File

@ -9,7 +9,9 @@
import UIKit import UIKit
@objcMembers public class AccordionMoleculeTableViewCell: MoleculeTableViewCell { @objcMembers public class AccordionMoleculeTableViewCell: MoleculeTableViewCell {
var accordionListItemModel: AccordionListItemModel? var accordionListItemModel: AccordionListItemModel? {
return listItemModel as? AccordionListItemModel
}
let accordionButton = createAccordionButton() let accordionButton = createAccordionButton()
static func createAccordionButton() -> MFCustomButton { static func createAccordionButton() -> MFCustomButton {
@ -30,10 +32,14 @@ import UIKit
override public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { override public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
accordionButton.isSelected = !accordionButton.isSelected accordionButton.isSelected = !accordionButton.isSelected
accordionButton.setTitle(accordionButton.isSelected ? "-" : "+", for: .normal) accordionButton.setTitle(accordionButton.isSelected ? "-" : "+", for: .normal)
guard let molecules = accordionListItemModel?.molecules else { guard let model = accordionListItemModel else {
return return
} }
guard let json = model.toJSON(),
let molecules = json.optionalArrayForKey("molecules") as? [[AnyHashable: Any]]
else { return }
if accordionButton.isSelected { if accordionButton.isSelected {
delegateObject?.moleculeDelegate?.addMolecules(molecules, sender: self, animation: .automatic) delegateObject?.moleculeDelegate?.addMolecules(molecules, sender: self, animation: .automatic)
} else { } else {

View File

@ -25,7 +25,6 @@ import UIKit
override public func setupView() { override public func setupView() {
super.setupView() super.setupView()
guard dropDown.superview == nil else { return }
addMolecule(dropDown) addMolecule(dropDown)
dropDown.observeDropdownChange = { [weak self] oldValue, newValue in dropDown.observeDropdownChange = { [weak self] oldValue, newValue in

View File

@ -8,43 +8,31 @@
import Foundation import Foundation
@objcMembers public class DropDownListItemModel: ContainerModel, ListItemModelProtocol { @objcMembers public class DropDownListItemModel: ListItemModel, MoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public static var identifier: String = "dropDownListItem" public static var identifier: String = "dropDownListItem"
public var molecules: [[ListItemModelProtocol]] public var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]
public var dropDown: ItemDropdownEntryFieldModel public var dropDown: ItemDropdownEntryFieldModel
public var backgroundColor: Color?
public var line: LineModel? = LineModel(type: .none)
public var hideArrow: Bool? = true
/// Defaults to set /// Defaults to set
func setDefaults() { public override func setDefaults() {
if useHorizontalMargins == nil { super.setDefaults()
useHorizontalMargins = true hideArrow = true
} line = LineModel(type: .none)
if useVerticalMargins == nil { style = "sectionFooter"
useVerticalMargins = true
}
if topMarginPadding == nil {
topMarginPadding = 24
}
if bottomMarginPadding == nil {
bottomMarginPadding = 0
}
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(molecules: [[ListItemModelProtocol]], dropDown: ItemDropdownEntryFieldModel) { public init(molecules: [[ListItemModelProtocol & MoleculeModelProtocol]], dropDown: ItemDropdownEntryFieldModel) {
self.molecules = molecules self.molecules = molecules
self.dropDown = dropDown self.dropDown = dropDown
super.init() super.init()
setDefaults()
} }
//-------------------------------------------------- //--------------------------------------------------
@ -55,8 +43,6 @@ import Foundation
case moleculeName case moleculeName
case molecules case molecules
case dropDown case dropDown
case line
case backgroundColor
} }
//-------------------------------------------------- //--------------------------------------------------
@ -65,16 +51,9 @@ import Foundation
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decodeMolecules2D(codingKey: .molecules) as? [[ListItemModelProtocol]] ?? [[]] molecules = try typeContainer.decodeMolecules2D(codingKey: .molecules) as? [[ListItemModelProtocol & MoleculeModelProtocol]] ?? [[]]
dropDown = try typeContainer.decode(ItemDropdownEntryFieldModel.self, forKey: .dropDown) dropDown = try typeContainer.decode(ItemDropdownEntryFieldModel.self, forKey: .dropDown)
if let lineModel = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) {
line = lineModel
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder) try super.init(from: decoder)
setDefaults()
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
@ -83,7 +62,5 @@ import Foundation
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModels2D(molecules, forKey: .molecules) try container.encodeModels2D(molecules, forKey: .molecules)
try container.encode(dropDown, forKey: .dropDown) try container.encode(dropDown, forKey: .dropDown)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(line, forKey: .line)
} }
} }

View File

@ -1,25 +1,22 @@
// //
// ListItem.swift // BaseListItemModel.swift
// MVMCoreUI // MVMCoreUI
// //
// Created by Suresh, Kamlesh on 10/3/19. // Created by Scott Pfeil on 2/12/20.
// Copyright © 2019 Suresh, Kamlesh. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
// A base class that has common list item boilerplate model stuffs.
import Foundation import Foundation
import MVMCore
@objcMembers public class ListItemModel: MoleculeContainerModel, ListItemModelProtocol { @objcMembers public class ListItemModel: ContainerModel, ListItemModelProtocol {
public static var identifier: String = "listItem"
public var backgroundColor: Color? public var backgroundColor: Color?
public var action: ActionModelProtocol? public var action: ActionModelProtocol?
public var hideArrow: Bool? public var hideArrow: Bool?
public var line: LineModel? public var line: LineModel?
public var style: String? = "standard" public var style: String?
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor case backgroundColor
case action case action
case hideArrow case hideArrow
@ -28,23 +25,20 @@ import MVMCore
} }
/// Defaults to set /// Defaults to set
func setDefaults() { public func setDefaults() {
if useHorizontalMargins == nil { if useHorizontalMargins == nil {
useHorizontalMargins = true useHorizontalMargins = true
} }
if useVerticalMargins == nil { if useVerticalMargins == nil {
useVerticalMargins = true useVerticalMargins = true
} }
if topMarginPadding == nil { if style == nil {
topMarginPadding = 24 style = "standard"
}
if bottomMarginPadding == nil {
bottomMarginPadding = 24
} }
} }
public override init(with moleculeModel: MoleculeModelProtocol) { public override init() {
super.init(with: moleculeModel) super.init()
setDefaults() setDefaults()
} }
@ -54,9 +48,7 @@ import MVMCore
action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType)
hideArrow = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideArrow) hideArrow = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideArrow)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
if let style = try typeContainer.decodeIfPresent(String.self, forKey: .style) { style = try typeContainer.decodeIfPresent(String.self, forKey: .style)
self.style = style
}
try super.init(from: decoder) try super.init(from: decoder)
setDefaults() setDefaults()
} }
@ -64,7 +56,6 @@ import MVMCore
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeModelIfPresent(action, forKey: .action) try container.encodeModelIfPresent(action, forKey: .action)
try container.encodeIfPresent(hideArrow, forKey: .hideArrow) try container.encodeIfPresent(hideArrow, forKey: .hideArrow)

View File

@ -0,0 +1,41 @@
//
// ListItem.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 10/3/19.
// Copyright © 2019 Suresh, Kamlesh. All rights reserved.
//
import Foundation
import MVMCore
@objcMembers public class MoleculeListItemModel: ListItemModel, MoleculeModelProtocol {
public class var identifier: String {
return "listItem"
}
public var molecule: MoleculeModelProtocol
private enum CodingKeys: String, CodingKey {
case moleculeName
case molecule
}
public init(with moleculeModel: MoleculeModelProtocol) {
molecule = moleculeModel
super.init()
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecule = try typeContainer.decodeMolecule(codingKey: .molecule)
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModel(molecule, forKey: .molecule)
}
}

View File

@ -8,14 +8,19 @@
import UIKit import UIKit
@objcMembers open class MoleculeTableViewCell: TableViewCell { @objcMembers open class MoleculeTableViewCell: TableViewCell {
// MARK: - MVMCoreUIMoleculeViewProtocol // MARK: - MVMCoreUIMoleculeViewProtocol
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData) super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? ListItemModel else { return }
guard let model = model as? MoleculeListItemModel else { return }
if molecule != nil { if molecule != nil {
(molecule as? ModelMoleculeViewProtocol)?.setWithModel(model.molecule, delegateObject, additionalData) (molecule as? ModelMoleculeViewProtocol)?.setWithModel(model.molecule, delegateObject, additionalData)
} else if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model.molecule, delegateObject, false) { } else if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model.molecule, delegateObject, false) {
addMolecule(moleculeView) addMolecule(moleculeView)
} }
@ -24,28 +29,28 @@ import UIKit
} }
public override class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { public override class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
guard let moleculeModel = (model as? ListItemModel)?.molecule else { guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule else { return "\(self)<>" }
return "\(self)<>"
}
let className = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moleculeModel) as? ModelMoleculeViewProtocol.Type let className = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moleculeModel) as? ModelMoleculeViewProtocol.Type
let moleculeName = className?.nameForReuse(moleculeModel, delegateObject) ?? moleculeModel.moleculeName ?? "" let moleculeName = className?.nameForReuse(moleculeModel, delegateObject) ?? moleculeModel.moleculeName ?? ""
return "\(self)<\(moleculeName)>" return "\(self)<\(moleculeName)>"
} }
public class func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { public class func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule),
let theClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON) else { let theClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)
return nil else { return nil }
}
return theClass.requiredModules?(moleculeJSON, delegateObject: delegateObject, error: error) return theClass.requiredModules?(moleculeJSON, delegateObject: delegateObject, error: error)
} }
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
guard let moleculeModel = (molecule as? MoleculeContainerModel)?.molecule, guard let moleculeModel = (molecule as? MoleculeContainerModel)?.molecule,
let classType = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moleculeModel) as? ModelMoleculeViewProtocol.Type, let classType = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moleculeModel) as? ModelMoleculeViewProtocol.Type,
let height = classType.estimatedHeight(forRow: moleculeModel, delegateObject: delegateObject) else { let height = classType.estimatedHeight(forRow: moleculeModel, delegateObject: delegateObject)
return 80 else { return 80 }
}
return max(2 * PaddingDefaultVerticalSpacing3, height) return max(2 * PaddingDefaultVerticalSpacing3, height)
} }
} }

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
@objcMembers public class StackItemModel: StackItemModelProtocol, MoleculeModelProtocol { @objcMembers public class StackItemModel: ContainerModel, StackItemModelProtocol, MoleculeModelProtocol {
public static var identifier: String = "simpleStackItem" public static var identifier: String = "simpleStackItem"
public var backgroundColor: Color? public var backgroundColor: Color?
public var spacing: CGFloat? public var spacing: CGFloat?
@ -19,4 +19,9 @@ import Foundation
self.init() self.init()
self.gone = gone self.gone = gone
} }
public convenience init(percent: Int) {
self.init()
self.percent = percent
}
} }

View File

@ -8,39 +8,36 @@
import UIKit import UIKit
public class TabsListItemModel: ContainerModel, ListItemModelProtocol { public class TabsListItemModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "tabsListItem" public static var identifier: String = "tabsListItem"
var tabs: TabsModel var tabs: TabsModel
var molecules: [[ListItemModelProtocol]] var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]
public var backgroundColor: Color?
public var hideArrow: Bool? = true
public var line: LineModel? = LineModel(type: .standard)
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case tabs case tabs
case molecules case molecules
case backgroundColor
case line
} }
public init(with tabs: TabsModel, molecules: [[ListItemModelProtocol]]) { public override func setDefaults() {
super.setDefaults()
hideArrow = true
action = nil
style = nil
topMarginPadding = 8
bottomMarginPadding = 0
}
public init(with tabs: TabsModel, molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]) {
self.tabs = tabs self.tabs = tabs
self.molecules = molecules self.molecules = molecules
super.init() super.init()
self.topMarginPadding = 8
self.bottomMarginPadding = 0
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
tabs = try typeContainer.decode(TabsModel.self, forKey: .tabs) tabs = try typeContainer.decode(TabsModel.self, forKey: .tabs)
molecules = try typeContainer.decodeMolecules2D(codingKey: .molecules) as! [[ListItemModelProtocol]] molecules = try typeContainer.decodeMolecules2D(codingKey: .molecules) as! [[ListItemModelProtocol & MoleculeModelProtocol]]
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
if let lineModel = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) {
line = lineModel
}
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -50,7 +47,5 @@ public class TabsListItemModel: ContainerModel, ListItemModelProtocol {
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(tabs, forKey: .tabs) try container.encode(tabs, forKey: .tabs)
try container.encodeModels2D(molecules, forKey: .molecules) try container.encodeModels2D(molecules, forKey: .molecules)
try container.encode(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(line, forKey: .line)
} }
} }

View File

@ -9,7 +9,9 @@
import UIKit import UIKit
@objcMembers public class TabsTableViewCell: TableViewCell { @objcMembers public class TabsTableViewCell: TableViewCell {
var tabsListItemModel: TabsListItemModel? var tabsListItemModel: TabsListItemModel? {
return listItemModel as? TabsListItemModel
}
let tabs = TopTabbar(frame: .zero) let tabs = TopTabbar(frame: .zero)
var delegateObject: MVMCoreUIDelegateObject? var delegateObject: MVMCoreUIDelegateObject?
var previousTabIndex = 0 var previousTabIndex = 0
@ -17,11 +19,7 @@ import UIKit
// MARK: - MFViewProtocol // MARK: - MFViewProtocol
override public func setupView() { override public func setupView() {
super.setupView() super.setupView()
guard tabs.superview == nil else {
return
}
tabs.paddingBeforeFirstTab = false tabs.paddingBeforeFirstTab = false
tabs.translatesAutoresizingMaskIntoConstraints = false tabs.translatesAutoresizingMaskIntoConstraints = false
tabs.delegate = self tabs.delegate = self
tabs.datasource = self tabs.datasource = self
@ -48,11 +46,18 @@ import UIKit
super.reset() super.reset()
tabs.reset() tabs.reset()
} }
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 46
}
} }
extension TabsTableViewCell: TopTabbarDelegate { extension TabsTableViewCell: TopTabbarDelegate {
public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool { public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool {
if let molecules = tabsListItemModel?.molecules[topTabbar.selectedIndex] { if let model = tabsListItemModel,
let json = model.toJSON(),
let json2d = json.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]] {
let molecules = json2d[topTabbar.selectedIndex]
delegateObject?.moleculeDelegate?.removeMolecules(molecules, sender: self, animation: index < tabs.selectedIndex ? .right : .left) delegateObject?.moleculeDelegate?.removeMolecules(molecules, sender: self, animation: index < tabs.selectedIndex ? .right : .left)
} }
previousTabIndex = tabs.selectedIndex previousTabIndex = tabs.selectedIndex
@ -60,7 +65,10 @@ extension TabsTableViewCell: TopTabbarDelegate {
} }
public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) { public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) {
if let molecules = tabsListItemModel?.molecules[index] { if let model = tabsListItemModel,
let json = model.toJSON(),
let json2d = json.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]] {
let molecules = json2d[index]
delegateObject?.moleculeDelegate?.addMolecules(molecules, sender: self, animation: index < previousTabIndex ? .left : .right) delegateObject?.moleculeDelegate?.addMolecules(molecules, sender: self, animation: index < previousTabIndex ? .left : .right)
} }
} }

View File

@ -27,7 +27,7 @@ import UIKit
headlineBodyLink.headlineBody.styleListItem() headlineBodyLink.headlineBody.styleListItem()
addSubview(headlineBodyLink) addSubview(headlineBodyLink)
addSubview(toggle) addSubview(toggle)
NSLayoutConstraint.pinSubviewsCenter(leftView: headlineBodyLink, rightView: toggle) NSLayoutConstraint.pinViews(leftView: headlineBodyLink, rightView: toggle, alignTop: false)
} }
// MARK: - MVMCoreUIMoleculeViewProtoco // MARK: - MVMCoreUIMoleculeViewProtoco

View File

@ -31,7 +31,7 @@ import UIKit
view.addSubview(headlineBody) view.addSubview(headlineBody)
view.addSubview(toggle) view.addSubview(toggle)
NSLayoutConstraint.pinSubviewsCenter(leftView: headlineBody, rightView: toggle) NSLayoutConstraint.pinViews(leftView: headlineBody, rightView: toggle, alignTop: false)
} }
// MARK:- ModelMoleculeViewProtocol // MARK:- ModelMoleculeViewProtocol

View File

@ -28,7 +28,7 @@ import UIKit
addSubview(label) addSubview(label)
addSubview(toggle) addSubview(toggle)
label.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) label.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical)
NSLayoutConstraint.pinSubviewsCenter(leftView: label, rightView: toggle) NSLayoutConstraint.pinViews(leftView: label, rightView: toggle, alignTop: false)
} }
// MARK:- ModelMoleculeViewProtocol // MARK:- ModelMoleculeViewProtocol

View File

@ -9,7 +9,7 @@
import Foundation import Foundation
@objcMembers public class HeadLineBodyCaretLinkImage: Container { @objcMembers public class HeadLineBodyCaretLinkImage: Container {
let headlineBody = HeadlineBody(frame: .zero) let headlineBody = HeadlineBody(frame: .zero)
let caretButton = CaretButton(frame: .zero) let caretButton = CaretLink(frame: .zero)
let backgroundImageView = MFLoadImageView(pinnedEdges: .all) let backgroundImageView = MFLoadImageView(pinnedEdges: .all)
let maxWidth: CGFloat = 350.0 let maxWidth: CGFloat = 350.0
static let heightConstant: CGFloat = 320.0 static let heightConstant: CGFloat = 320.0
@ -66,13 +66,6 @@ import Foundation
} }
// MARK: - MVMCoreUIMoleculeViewProtocol // MARK: - MVMCoreUIMoleculeViewProtocol
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
backgroundImageView.setWithJSON(json?.optionalDictionaryForKey("image"), delegateObject: delegateObject, additionalData: additionalData)
headlineBody.setWithJSON(json?.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData)
caretButton.setWithJSON(json?.optionalDictionaryForKey("caretLink"), delegateObject: delegateObject, additionalData: additionalData)
}
open override func reset() { open override func reset() {
super.reset() super.reset()
headlineBody.reset() headlineBody.reset()

View File

@ -24,9 +24,8 @@ open class HeadlineBody: View {
// MARK: - Styling // MARK: - Styling
func style(with styleString: String?) { func style(with styleString: String?) {
guard let styleString = styleString else { guard let styleString = styleString else { return }
return
}
switch styleString { switch styleString {
case "header": case "header":
stylePageHeader() stylePageHeader()
@ -72,10 +71,9 @@ open class HeadlineBody: View {
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
guard subviews.count == 0 else {
return guard subviews.isEmpty else { return }
}
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .clear backgroundColor = .clear
clipsToBounds = true clipsToBounds = true
@ -86,9 +84,9 @@ open class HeadlineBody: View {
view.addSubview(headlineLabel) view.addSubview(headlineLabel)
view.addSubview(messageLabel) view.addSubview(messageLabel)
headlineLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) headlineLabel.setContentHuggingPriority(.required, for: .vertical)
messageLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) messageLabel.setContentHuggingPriority(.required, for: .vertical)
view.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) view.setContentHuggingPriority(.required, for: .vertical)
headlineLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true headlineLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
@ -110,7 +108,10 @@ open class HeadlineBody: View {
view.bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 0).isActive = true view.bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 0).isActive = true
} }
//--------------------------------------------------
// MARK: - Constraining // MARK: - Constraining
//--------------------------------------------------
public func setSpacing() { public func setSpacing() {
if headlineLabel.hasText && messageLabel.hasText { if headlineLabel.hasText && messageLabel.hasText {
spaceBetweenLabels?.constant = spaceBetweenLabelsConstant spaceBetweenLabels?.constant = spaceBetweenLabelsConstant
@ -119,17 +120,18 @@ open class HeadlineBody: View {
} }
} }
// MARK:- ModelMoleculeViewProtocol //--------------------------------------------------
// MARK: - ModelMoleculeViewProtocol
//--------------------------------------------------
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 58 return 58
} }
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData) super.setWithModel(model, delegateObject, additionalData)
guard let headlineBodyModel = model as? HeadlineBodyModel else {
return guard let headlineBodyModel = model as? HeadlineBodyModel else { return }
}
style(with: headlineBodyModel.style) style(with: headlineBodyModel.style)
@ -137,7 +139,10 @@ open class HeadlineBody: View {
messageLabel.setWithModel(headlineBodyModel.body, delegateObject, additionalData) messageLabel.setWithModel(headlineBodyModel.body, delegateObject, additionalData)
} }
//--------------------------------------------------
// MARK: - MVMCoreUIMoleculeViewProtocol // MARK: - MVMCoreUIMoleculeViewProtocol
//--------------------------------------------------
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
@ -159,4 +164,3 @@ open class HeadlineBody: View {
return 58 return 58
} }
} }

View File

@ -10,7 +10,6 @@ import Foundation
@objcMembers public class HeadlineBodyModel: MoleculeModelProtocol { @objcMembers public class HeadlineBodyModel: MoleculeModelProtocol {
public static var identifier: String = "headlineBody" public static var identifier: String = "headlineBody"
public var moleculeName: String?
public var headline: LabelModel? public var headline: LabelModel?
public var body: LabelModel? public var body: LabelModel?
public var style: String? public var style: String?
@ -20,4 +19,3 @@ import Foundation
self.headline = headline self.headline = headline
} }
} }

View File

@ -11,7 +11,7 @@ import Foundation
public extension MVMCoreUIMoleculeMappingObject { public extension MVMCoreUIMoleculeMappingObject {
func register<M: Model, V: MVMCoreUIMoleculeViewProtocol>(viewClass: V.Type, viewModelClass: M.Type) { func register<M: Model, V: MVMCoreUIMoleculeViewProtocol>(viewClass: V.Type, viewModelClass: M.Type) {
ModelRegistry.register(viewModelClass) try? ModelRegistry.register(viewModelClass)
MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(viewClass, forKey: viewModelClass.identifier as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(viewClass, forKey: viewModelClass.identifier as NSString)
} }

View File

@ -22,8 +22,7 @@
@"stack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]], @"stack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]],
@"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]], @"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]],
@"list" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]], @"list" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]],
@"threeLayer" : @"threeLayer" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]]
[[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]]
} mutableCopy]; } mutableCopy];
}); });
return viewControllerMapping; return viewControllerMapping;

View File

@ -23,8 +23,8 @@ public protocol MoleculeDelegateProtocol {
func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation)
//optional //optional
func addMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation)
func removeMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation)
} }
extension MoleculeDelegateProtocol { extension MoleculeDelegateProtocol {
@ -40,11 +40,11 @@ extension MoleculeDelegateProtocol {
// Do nothing // Do nothing
} }
public func addMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// Do nothing // Do nothing
} }
public func removeMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// Do nothing // Do nothing
} }
} }

View File

@ -18,19 +18,19 @@ import Foundation
// Label // Label
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Label.self, viewModelClass: LabelModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Label.self, viewModelClass: LabelModel.self)
//need to move labelattributemodel to different method // need to move labelattributemodel to different method
ModelRegistry.register(LabelAttributeFontModel.self) try? ModelRegistry.register(LabelAttributeFontModel.self)
ModelRegistry.register(LabelAttributeColorModel.self) try? ModelRegistry.register(LabelAttributeColorModel.self)
//ModelRegistry.register(LabelAttributeImageModel.self) // We need to separate the registry by types due to collisions... try? ModelRegistry.register(LabelAttributeImageModel.self) // We need to separate the registry by types due to collisions...
ModelRegistry.register(LabelAttributeUnderlineModel.self) try? ModelRegistry.register(LabelAttributeUnderlineModel.self)
ModelRegistry.register(LabelAttributeStrikeThroughModel.self) try? ModelRegistry.register(LabelAttributeStrikeThroughModel.self)
ModelRegistry.register(LabelAttributeActionModel.self) try? ModelRegistry.register(LabelAttributeActionModel.self)
// Buttons // Buttons
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TwoButtonView.self, viewModelClass: TwoButtonViewModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TwoButtonView.self, viewModelClass: TwoButtonViewModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Link.self, viewModelClass: LinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Link.self, viewModelClass: LinkModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretButton.self, viewModelClass: CaretLinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretLink.self, viewModelClass: CaretLinkModel.self)
// Entry Field // Entry Field
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TextEntryField.self, viewModelClass: TextEntryFieldModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TextEntryField.self, viewModelClass: TextEntryFieldModel.self)
@ -40,7 +40,6 @@ import Foundation
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: DateDropdownEntryField.self, viewModelClass: DateDropdownEntryFieldModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: DateDropdownEntryField.self, viewModelClass: DateDropdownEntryFieldModel.self)
// Other Atoms // Other Atoms
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Label.self, viewModelClass: LabelModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MultiProgress.self, viewModelClass: MultiProgressBarModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MultiProgress.self, viewModelClass: MultiProgressBarModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretView.self, viewModelClass: CaretViewModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretView.self, viewModelClass: CaretViewModel.self)
@ -55,6 +54,8 @@ import Foundation
// Horizontal Combination Molecules // Horizontal Combination Molecules
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self)
// Vertical Combination Molecules // Vertical Combination Molecules
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self)
@ -71,9 +72,10 @@ import Foundation
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyToggle.self, viewModelClass: HeadlineBodyToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyToggle.self, viewModelClass: HeadlineBodyToggleModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableIconWithRightCaret.self, viewModelClass: ListLeftVariableIconWithRightCaretModel.self)
// List items // List items
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: ListItemModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: MoleculeListItemModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: DropDownFilterTableViewCell.self, viewModelClass: DropDownListItemModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: DropDownFilterTableViewCell.self, viewModelClass: DropDownListItemModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: AccordionMoleculeTableViewCell.self, viewModelClass: AccordionListItemModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: AccordionMoleculeTableViewCell.self, viewModelClass: AccordionListItemModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TabsTableViewCell.self, viewModelClass: TabsListItemModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TabsTableViewCell.self, viewModelClass: TabsListItemModel.self)
@ -105,6 +107,6 @@ import Foundation
MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(MVMCoreUIPageControl.self, forKey: "barsPager" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(MVMCoreUIPageControl.self, forKey: "barsPager" as NSString)
// TODO: Need View // TODO: Need View
ModelRegistry.register(TabsModel.self) try? ModelRegistry.register(TabsModel.self)
} }
} }

View File

@ -9,6 +9,9 @@
import Foundation import Foundation
@objcMembers public class ListPageTemplateModel: TemplateModelProtocol { @objcMembers public class ListPageTemplateModel: TemplateModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "list" public static var identifier: String = "list"
@ -17,16 +20,24 @@ import Foundation
public var isAtomicTabs: Bool? public var isAtomicTabs: Bool?
public var header: MoleculeModelProtocol? public var header: MoleculeModelProtocol?
public var molecules: [ListItemModelProtocol]? public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]?
public var footer: MoleculeModelProtocol? public var footer: MoleculeModelProtocol?
public var line: LineModel? public var line: LineModel?
public init(pageType: String, screenHeading: String?, molecules: [ListItemModelProtocol]) { //--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(pageType: String, screenHeading: String?, molecules: [ListItemModelProtocol & MoleculeModelProtocol]) {
self.pageType = pageType self.pageType = pageType
self.screenHeading = screenHeading self.screenHeading = screenHeading
self.molecules = molecules self.molecules = molecules
} }
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case pageType case pageType
@ -38,11 +49,15 @@ import Foundation
case isAtomicTabs case isAtomicTabs
} }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
pageType = try typeContainer.decode(String.self, forKey: .pageType) pageType = try typeContainer.decode(String.self, forKey: .pageType)
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading) screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
molecules = try typeContainer.decodeMoleculesIfPresent(codingKey: .molecules) as? [ListItemModelProtocol] molecules = try typeContainer.decodeMoleculesIfPresent(codingKey: .molecules) as? [ListItemModelProtocol & MoleculeModelProtocol]
isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs)
header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header) header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header)
footer = try typeContainer.decodeMoleculeIfPresent(codingKey: .footer) footer = try typeContainer.decodeMoleculeIfPresent(codingKey: .footer)

View File

@ -9,52 +9,67 @@
import UIKit import UIKit
open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol { open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol {
//--------------------------------------------------
// MARK: - Stored Properties
//--------------------------------------------------
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]?
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: ListItemModelProtocol)]?
var observer: NSKeyValueObservation? var observer: NSKeyValueObservation?
public var templateModel: ListPageTemplateModel? public var templateModel: ListPageTemplateModel?
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
@objc public override func parsePageJSON() throws { @objc public override func parsePageJSON() throws {
try parseTemplateJSON() try parseTemplateJSON()
} }
open override var loadObject: MVMCoreLoadObject? { open override var loadObject: MVMCoreLoadObject? {
didSet { didSet {
if loadObject != oldValue { guard loadObject != oldValue else { return }
updateRequiredModules()
observer?.invalidate() updateRequiredModules()
if let newObject = loadObject { observer?.invalidate()
observer = newObject.observe(\MVMCoreLoadObject.pageJSON, options: [.old, .new]) { [weak self] (object, change) in if let newObject = loadObject {
self?.updateRequiredModules() observer = newObject.observe(\MVMCoreLoadObject.pageJSON, options: [.old, .new]) { [weak self] object, change in
} self?.updateRequiredModules()
} }
} }
} }
} }
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
open override func viewForTop() -> UIView { open override func viewForTop() -> UIView {
guard let headerModel = templateModel?.header, guard let headerModel = templateModel?.header,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(headerModel, delegateObject() as? MVMCoreUIDelegateObject, false) else { let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(headerModel, delegateObject() as? MVMCoreUIDelegateObject, false)
return super.viewForTop() else { return super.viewForTop() }
}
// Temporary, Default the horizontal padding // Temporary, Default the horizontal padding
if var container = templateModel?.header as? ContainerModelProtocol, container.useHorizontalMargins == nil { if var container = templateModel?.header as? ContainerModelProtocol, container.useHorizontalMargins == nil {
container.useHorizontalMargins = true container.useHorizontalMargins = true
} }
return molecule return molecule
} }
override open func viewForBottom() -> UIView { override open func viewForBottom() -> UIView {
guard let footerModel = templateModel?.footer, guard let footerModel = templateModel?.footer,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(footerModel, delegateObject() as? MVMCoreUIDelegateObject, false) else { let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(footerModel, delegateObject() as? MVMCoreUIDelegateObject, false)
return super.viewForBottom() else { return super.viewForBottom() }
}
return molecule return molecule
} }
open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool { open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool {
guard super.shouldFinishProcessingLoad(loadObject, error: error) else { return false } guard super.shouldFinishProcessingLoad(loadObject, error: error) else { return false }
// This template requires atleast one of the three layers. // This template requires atleast one of the three layers.
if templateModel?.header == nil, if templateModel?.header == nil,
templateModel?.molecules?.count ?? 0 == 0, templateModel?.molecules?.count ?? 0 == 0,
@ -72,7 +87,10 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
registerWithTable() registerWithTable()
} }
// MARK: - table //--------------------------------------------------
// MARK: - Table View
//--------------------------------------------------
open override func registerWithTable() { open override func registerWithTable() {
super.registerWithTable() super.registerWithTable()
guard let moleculesInfo = moleculesInfo else { return } guard let moleculesInfo = moleculesInfo else { return }
@ -84,9 +102,9 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
guard let moleculeInfo = moleculesInfo?[indexPath.row], guard let moleculeInfo = moleculesInfo?[indexPath.row],
let estimatedHeight = (moleculeInfo.class as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: moleculeInfo.molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) else { let estimatedHeight = (moleculeInfo.class as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: moleculeInfo.molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject)
return 0 else { return 0 }
}
return estimatedHeight return estimatedHeight
} }
@ -95,18 +113,22 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
} }
open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let moleculeInfo = moleculesInfo?[indexPath.row], guard let moleculeInfo = moleculesInfo?[indexPath.row],
let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier) else { let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier)
return UITableViewCell() else { return UITableViewCell() }
}
let delegate = delegateObject() as? MVMCoreUIDelegateObject let delegate = delegateObject() as? MVMCoreUIDelegateObject
let moleculeCell = cell as? MVMCoreUIMoleculeViewProtocol let moleculeCell = cell as? MVMCoreUIMoleculeViewProtocol
moleculeCell?.reset?() moleculeCell?.reset?()
if let protocolCell = cell as? MoleculeListCellProtocol { if let protocolCell = cell as? MoleculeListCellProtocol {
protocolCell.setLines(with: templateModel?.line, delegateObject: delegate, additionalData: nil, indexPath: indexPath) protocolCell.setLines(with: templateModel?.line, delegateObject: delegate, additionalData: nil, indexPath: indexPath)
} }
(moleculeCell as? ModelMoleculeViewProtocol)?.setWithModel(moleculeInfo.molecule, delegate, nil) (moleculeCell as? ModelMoleculeViewProtocol)?.setWithModel(moleculeInfo.molecule, delegate, nil)
moleculeCell?.updateView(tableView.bounds.width) moleculeCell?.updateView(tableView.bounds.width)
return cell return cell
} }
@ -118,16 +140,18 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
} }
open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? MoleculeListCellProtocol { if let cell = tableView.cellForRow(at: indexPath) as? MoleculeListCellProtocol {
cell.didSelectCell(at: indexPath, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) cell.didSelectCell(at: indexPath, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil)
} }
} }
// MARK: - cache handling //--------------------------------------------------
// MARK: - Cache Handling
//--------------------------------------------------
open override func pageTypesToListenFor() -> [Any]? { open override func pageTypesToListenFor() -> [Any]? {
guard let pageType = self.pageType else { guard let pageType = self.pageType else { return super.pageTypesToListenFor() }
return super.pageTypesToListenFor()
}
return [pageType] return [pageType]
} }
@ -135,8 +159,12 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
return loadObject?.requestParameters?.modules return loadObject?.requestParameters?.modules
} }
//--------------------------------------------------
// MARK: - MoleculeDelegateProtocol // MARK: - MoleculeDelegateProtocol
//--------------------------------------------------
open override func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) { open override func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {
if let tableView = tableView { if let tableView = tableView {
let point = molecule.convert(molecule.bounds.origin, to: tableView) let point = molecule.convert(molecule.bounds.origin, to: tableView)
if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false { if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
@ -148,10 +176,10 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
public override func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { public override func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
var tmpMolecules = [ListItemModelProtocol]() var tmpMolecules = [ListItemModelProtocol & MoleculeModelProtocol]()
molecules.forEach { molecule in molecules.forEach { molecule in
if let data = try? JSONSerialization.data(withJSONObject: molecule), let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data) { if let data = try? JSONSerialization.data(withJSONObject: molecule), let listItemModel = try? JSONDecoder().decode(MoleculeListItemModel.self, from: data) {
tmpMolecules.append(listItemModel) tmpMolecules.append(listItemModel)
} }
} }
@ -159,6 +187,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
DispatchQueue.main.async { DispatchQueue.main.async {
guard let indexPath = self.tableView?.indexPath(for: sender) else { return } guard let indexPath = self.tableView?.indexPath(for: sender) else { return }
var indexPaths: [IndexPath] = [] var indexPaths: [IndexPath] = []
for molecule in tmpMolecules { for molecule in tmpMolecules {
if let info = self.getMoleculeInfo(with: molecule) { if let info = self.getMoleculeInfo(with: molecule) {
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier) self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
@ -167,6 +196,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
indexPaths.append(IndexPath(row: index, section: 0)) indexPaths.append(IndexPath(row: index, section: 0))
} }
} }
self.tableView?.insertRows(at: indexPaths, with: animation) self.tableView?.insertRows(at: indexPaths, with: animation)
self.updateViewConstraints() self.updateViewConstraints()
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
@ -175,34 +205,39 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
public override func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { public override func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
var tmpMolecules = [ListItemModelProtocol]() var tmpMolecules = [ListItemModelProtocol & MoleculeModelProtocol]()
molecules.forEach { molecule in molecules.forEach { molecule in
if let data = try? JSONSerialization.data(withJSONObject: molecule), let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data) { if let data = try? JSONSerialization.data(withJSONObject: molecule),
let listItemModel = try? JSONDecoder().decode(MoleculeListItemModel.self, from: data) {
tmpMolecules.append(listItemModel) tmpMolecules.append(listItemModel)
} }
} }
var indexPaths: [IndexPath] = [] var indexPaths: [IndexPath] = []
//TODO: cehck for molecule protocola eqality //TODO: cehck for molecule protocola eqality
for molecule in tmpMolecules { for molecule in tmpMolecules {
if let removeIndex = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in if let removeIndex = moleculesInfo?.firstIndex(where: { molecule.toJSON() == $0.molecule.toJSON() }) {
return molecule.toJSONString() == moleculeInfo.molecule.toJSONString()
}) {
moleculesInfo?.remove(at: removeIndex) moleculesInfo?.remove(at: removeIndex)
indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0)) indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0))
} }
} }
self.tableView?.deleteRows(at: indexPaths, with: animation)
self.updateViewConstraints() tableView?.deleteRows(at: indexPaths, with: animation)
self.view.layoutIfNeeded() updateViewConstraints()
view.layoutIfNeeded()
} }
public func addMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// This dispatch is needed to fix a race condition that can occur if this function is called during the table setup. // This dispatch is needed to fix a race condition that can occur if this function is called during the table setup.
DispatchQueue.main.async { DispatchQueue.main.async {
guard let indexPath = self.tableView?.indexPath(for: sender) else { return } guard let indexPath = self.tableView?.indexPath(for: sender) else { return }
var indexPaths: [IndexPath] = [] var indexPaths: [IndexPath] = []
for molecule in molecules { for molecule in molecules {
if let info = self.getMoleculeInfo(with: molecule) { if let info = self.getMoleculeInfo(with: molecule) {
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier) self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
@ -211,42 +246,50 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
indexPaths.append(IndexPath(row: index, section: 0)) indexPaths.append(IndexPath(row: index, section: 0))
} }
} }
self.tableView?.insertRows(at: indexPaths, with: animation) self.tableView?.insertRows(at: indexPaths, with: animation)
self.updateViewConstraints() self.updateViewConstraints()
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
} }
} }
public func removeMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
var indexPaths: [IndexPath] = [] var indexPaths: [IndexPath] = []
//TODO: cehck for molecule protocola eqality //TODO: cehck for molecule protocola eqality
for molecule in molecules { for molecule in molecules {
if let removeIndex = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in if let removeIndex = moleculesInfo?.firstIndex(where: { molecule.toJSON() == $0.molecule.toJSON() }) {
return molecule.toJSONString() == moleculeInfo.molecule.toJSONString()
}) {
moleculesInfo?.remove(at: removeIndex) moleculesInfo?.remove(at: removeIndex)
indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0)) indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0))
} }
} }
self.tableView?.deleteRows(at: indexPaths, with: animation)
self.updateViewConstraints() tableView?.deleteRows(at: indexPaths, with: animation)
self.view.layoutIfNeeded() updateViewConstraints()
view.layoutIfNeeded()
} }
//--------------------------------------------------
// MARK: - Convenience // MARK: - Convenience
//--------------------------------------------------
/// Returns the (identifier, class) of the molecule for the given map. /// Returns the (identifier, class) of the molecule for the given map.
func getMoleculeInfo(with listItem: ListItemModelProtocol?) -> (identifier: String, class: AnyClass, molecule: ListItemModelProtocol)? { func getMoleculeInfo(with listItem: (ListItemModelProtocol & MoleculeModelProtocol)?) -> (identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)? {
guard let listItem = listItem, guard let listItem = listItem,
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(listItem), let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(listItem),
let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol.Type)?.nameForReuse(listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName else { let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol.Type)?.nameForReuse(listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName
return nil else { return nil }
}
return (moleculeName, moleculeClass, listItem) return (moleculeName, moleculeClass, listItem)
} }
/// Sets up the molecule list and ensures no errors loading all content. /// Sets up the molecule list and ensures no errors loading all content.
func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: ListItemModelProtocol)]? { func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]? {
var moleculeList: [(identifier: String, class: AnyClass, molecule: ListItemModelProtocol)] = []
var moleculeList: [(identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)] = []
if let molecules = templateModel?.molecules { if let molecules = templateModel?.molecules {
for molecule in molecules { for molecule in molecules {
if let info = getMoleculeInfo(with: molecule) { if let info = getMoleculeInfo(with: molecule) {
@ -254,6 +297,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
} }
} }
} }
return moleculeList.count > 0 ? moleculeList : nil return moleculeList.count > 0 ? moleculeList : nil
} }
@ -271,15 +315,19 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
/// Gets modules required by the loadObject.pageJSON. /// Gets modules required by the loadObject.pageJSON.
open func requiredModules() -> [Any]? { open func requiredModules() -> [Any]? {
let modules: NSMutableArray = [] let modules: NSMutableArray = []
let delegate = delegateObject() as? MVMCoreUIDelegateObject let delegate = delegateObject() as? MVMCoreUIDelegateObject
MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: nil) MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: nil)
MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: nil) MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: nil)
if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] { if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] {
for molecule in molecules { for molecule in molecules {
MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: molecule, delegateObject: delegate, moduleList: modules, errorList: nil) MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: molecule, delegateObject: delegate, moduleList: modules, errorList: nil)
} }
} }
return modules as? [Any] return modules as? [Any]
} }
} }

View File

@ -14,6 +14,7 @@ public protocol TemplateProtocol: class {
} }
public extension TemplateProtocol where Self: MFViewController { public extension TemplateProtocol where Self: MFViewController {
func parseTemplateJSON() throws { func parseTemplateJSON() throws {
guard let pageJSON = self.loadObject?.pageJSON else { return } guard let pageJSON = self.loadObject?.pageJSON else { return }
let data = try JSONSerialization.data(withJSONObject: pageJSON) let data = try JSONSerialization.data(withJSONObject: pageJSON)

View File

@ -41,7 +41,7 @@ import Foundation
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading) screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs)
header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header) header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header)
header = try typeContainer.decodeMoleculeIfPresent(codingKey: .middle) middle = try typeContainer.decodeMoleculeIfPresent(codingKey: .middle)
footer = try typeContainer.decodeMoleculeIfPresent(codingKey: .footer) footer = try typeContainer.decodeMoleculeIfPresent(codingKey: .footer)
} }

View File

@ -30,16 +30,16 @@
- (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; - (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout;
// Used primarily for when button presses will expand or collapse. (Short view button will need to be set manually) // Used primarily for when button presses will expand or collapse. (Short view button will need to be set manually)
- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; - (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout;
- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; - (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout;
// Used when button uses standard action map. // Used when button uses standard action map.
- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; - (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout;
// Convenience change functions // Convenience change functions
- (void)setTopMessage:(nullable NSString *)topMessage; - (void)setTopMessage:(nullable NSString *)topMessage;
- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; - (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; - (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler;
// Setters for making buttons expand and collapse the cell. // Setters for making buttons expand and collapse the cell.
- (void)setButtonPressToExpand; - (void)setButtonPressToExpand;

View File

@ -41,10 +41,10 @@
- (void)setupTopAlertWithButton:(MVMCoreUITopAlertMainView *)topAlertWithButton; - (void)setupTopAlertWithButton:(MVMCoreUITopAlertMainView *)topAlertWithButton;
// Sets up the whole view without setting button action. // Sets up the whole view without setting button action.
- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle; - (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle;
// Sets up the whole view while setting button action. // Sets up the whole view while setting button action.
- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; - (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
@end @end
@ -97,14 +97,8 @@
[self setupTopAlertWithButton:topAlertWithButton]; [self setupTopAlertWithButton:topAlertWithButton];
// Sets the color // Sets the color
if (topAlertObject.backgroundColor) { self.shortView.label.textColor = topAlertObject.textColor ?: [[MVMCoreUITopAlertView sharedGlobal] getContentColorForType:topAlertObject.type];
self.backgroundColor = topAlertObject.backgroundColor; self.backgroundColor = topAlertObject.backgroundColor ?: [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type];
} else {
self.backgroundColor = [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type];
}
if (topAlertObject.textColor) {
self.shortView.label.textColor = topAlertObject.textColor;
}
if (topAlertWithButton.label.text.length > 0) { if (topAlertWithButton.label.text.length > 0) {
[self expand:NO]; [self expand:NO];
@ -112,8 +106,10 @@
} else { } else {
// Old style, has no top alert and main view is limited. // Old style, has no top alert and main view is limited.
self.backgroundColor = [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; [self setupTopMessage:nil]; self.backgroundColor = [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type];
MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:self.backgroundColor message:topAlertObject.message subMessage:nil closeButton:YES animationDelegate:animationDelegate]; UIColor *contentColor = [[MVMCoreUITopAlertView sharedGlobal] getContentColorForType:topAlertObject.type];
[self setupTopMessage:nil];
MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:self.backgroundColor contentColor:contentColor message:topAlertObject.message subMessage:nil closeButton:YES animationDelegate:animationDelegate];
[self setupTopAlertWithButton:topAlertWithButton]; [self setupTopAlertWithButton:topAlertWithButton];
[self expand:NO]; [self expand:NO];
} }
@ -121,29 +117,29 @@
return self; return self;
} }
- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { - (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout {
if ([self init]) { if ([self init]) {
self.animationDelegate = animationDelegate; self.animationDelegate = animationDelegate;
self.viewToLayout = viewTolayout; self.viewToLayout = viewTolayout;
[self setupViewWithTopMessage:topMessage message:message subMessage:nil buttonTitle:buttonTitle]; [self setupViewWithTopMessage:topMessage message:message subMessage:nil contentColor:contentColor buttonTitle:buttonTitle];
} }
return self; return self;
} }
- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { - (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout {
if ([self init]) { if ([self init]) {
self.animationDelegate = animationDelegate; self.animationDelegate = animationDelegate;
self.viewToLayout = viewTolayout; self.viewToLayout = viewTolayout;
[self setupViewWithTopMessage:topMessage message:message subMessage:subMessage buttonTitle:buttonTitle]; [self setupViewWithTopMessage:topMessage message:message subMessage:subMessage contentColor:contentColor buttonTitle:buttonTitle];
} }
return self; return self;
} }
- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { - (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout {
if ([self init]) { if ([self init]) {
self.animationDelegate = animationDelegate; self.animationDelegate = animationDelegate;
self.viewToLayout = viewTolayout; self.viewToLayout = viewTolayout;
[self setupViewWithTopMessage:topMessage message:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; [self setupViewWithTopMessage:topMessage message:message subMessage:subMessage contentColor:contentColor actionMap:actionMap additionalData:additionalData];
} }
return self; return self;
} }
@ -174,19 +170,19 @@
[NSLayoutConstraint constraintPinSubview:topAlertWithButton pinTop:NO topConstant:0 pinBottom:YES bottomConstant:0 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0]; [NSLayoutConstraint constraintPinSubview:topAlertWithButton pinTop:NO topConstant:0 pinBottom:YES bottomConstant:0 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0];
} }
- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle { - (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle {
[self setupTopMessage:topMessage]; [self setupTopMessage:topMessage];
MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] message:message subMessage:subMessage buttonTitle:buttonTitle userActionHandler:nil]; MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] contentColor:contentColor message:message subMessage:subMessage buttonTitle:buttonTitle userActionHandler:nil];
[self setupTopAlertWithButton:topAlertWithButton]; [self setupTopAlertWithButton:topAlertWithButton];
} }
- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData {
[self setupTopMessage:topMessage]; [self setupTopMessage:topMessage];
MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] message:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] contentColor:contentColor message:message subMessage:subMessage actionMap:actionMap additionalData:additionalData];
[self setupTopAlertWithButton:topAlertWithButton]; [self setupTopAlertWithButton:topAlertWithButton];
} }
@ -204,17 +200,17 @@
}]; }];
} }
- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData {
[MVMCoreDispatchUtility performBlockOnMainThread:^{ [MVMCoreDispatchUtility performBlockOnMainThread:^{
[self setTopMessage:topMessage]; [self setTopMessage:topMessage];
[self.buttonView setupWithMessage:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; [self.buttonView setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData];
}]; }];
} }
- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { - (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler {
[MVMCoreDispatchUtility performBlockOnMainThread:^{ [MVMCoreDispatchUtility performBlockOnMainThread:^{
[self setTopMessage:topMessage]; [self setTopMessage:topMessage];
[self.buttonView setupWithMessage:message subMessage:subMessage buttonTitle:buttonTitle userActionHandler:userActionHandler]; [self.buttonView setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:buttonTitle userActionHandler:userActionHandler];
}]; }];
} }

View File

@ -22,16 +22,16 @@
// Standard // Standard
- (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate; - (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate; - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
// inits with images // inits with images
- (nullable instancetype)initWithColor:(nonnull UIColor *)color imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate; - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
- (nullable instancetype)initWithColor:(nonnull UIColor *)color imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate; - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
// Setters for label and button. // Setters for label and button.
- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; - (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; - (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler;
// Setters for button. // Setters for button.
- (void)setupButtonWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; - (void)setupButtonWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
@ -40,13 +40,13 @@
#pragma mark - legacy inits #pragma mark - legacy inits
// Legacy init: inits with a label and button, no close button or icon. // Legacy init: inits with a label and button, no close button or icon.
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
// Legacy init: inits with a label and possible icon and close button. No main button. // Legacy init: inits with a label and possible icon and close button. No main button.
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate; - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
// Legacy init: inits with a label and button, no close button or icon. If passing in a block to use for the button, the top alert delegate button functions will not be called. // Legacy init: inits with a label and button, no close button or icon. If passing in a block to use for the button, the top alert delegate button functions will not be called.
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler;
@end @end

View File

@ -60,52 +60,49 @@
- (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate { - (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate {
if ([self init]) { if ([self init]) {
if (topAlertObject.backgroundColor) { UIColor *contentColor = topAlertObject.textColor ?: [[MVMCoreUITopAlertView sharedGlobal] getContentColorForType:topAlertObject.type];
self.backgroundColor = topAlertObject.backgroundColor; self.backgroundColor = topAlertObject.backgroundColor ?: [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type];
} else {
self.backgroundColor = [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type];
}
[self setupViewWithLabelAndImage:topAlertObject.imageNameOrURL topImage:topAlertObject.aboveTextImageString]; [self setupViewWithLabelAndImage:topAlertObject.imageNameOrURL topImage:topAlertObject.aboveTextImageString];
[self setupCloseButton:topAlertObject.useCloseButton animationDelegate:animationDelegate]; [self setupCloseButton:topAlertObject.useCloseButton animationDelegate:animationDelegate];
[self setupWithMessage:topAlertObject.title subMessage:topAlertObject.message color:topAlertObject.textColor actionMap:topAlertObject.buttonMap additionalData:topAlertObject.additionalData]; [self setupWithMessage:topAlertObject.title subMessage:topAlertObject.message color:contentColor actionMap:topAlertObject.buttonMap additionalData:topAlertObject.additionalData];
} }
return self; return self;
} }
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate { - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate {
// Handles all scenarios. // Handles all scenarios.
if ([self init]) { if ([self init]) {
self.backgroundColor = color; self.backgroundColor = color;
[self setupViewWithLabelAndImage:nil topImage:nil]; [self setupViewWithLabelAndImage:nil topImage:nil];
[self setupCloseButton:closeButton animationDelegate:animationDelegate]; [self setupCloseButton:closeButton animationDelegate:animationDelegate];
[self setupWithMessage:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; [self setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData];
} }
return self; return self;
} }
#pragma mark - inits with images #pragma mark - inits with images
- (nullable instancetype)initWithColor:(nonnull UIColor *)color imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate { - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate {
// Handles all scenarios. // Handles all scenarios.
if ([self init]) { if ([self init]) {
self.backgroundColor = color; self.backgroundColor = color;
[self setupViewWithLabelAndImage:imageURL topImage:nil]; [self setupViewWithLabelAndImage:imageURL topImage:nil];
[self setupCloseButton:closeButton animationDelegate:animationDelegate]; [self setupCloseButton:closeButton animationDelegate:animationDelegate];
[self setupWithMessage:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; [self setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData];
} }
return self; return self;
} }
- (nullable instancetype)initWithColor:(nonnull UIColor *)color imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate { - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate {
// No main button. // No main button.
if ([self init]) { if ([self init]) {
self.backgroundColor = color; self.backgroundColor = color;
[self setupViewWithLabelAndImage:imageURL topImage:nil]; [self setupViewWithLabelAndImage:imageURL topImage:nil];
[self setupCloseButton:closeButton animationDelegate:animationDelegate]; [self setupCloseButton:closeButton animationDelegate:animationDelegate];
[self setupWithMessage:message subMessage:subMessage buttonTitle:nil userActionHandler:NULL]; [self setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:nil userActionHandler:NULL];
} }
return self; return self;
} }
@ -173,7 +170,7 @@
if (closeButton && !self.closeButton) { if (closeButton && !self.closeButton) {
self.closeButton = [self addCloseButtonWithAnimationDelegate:animationDelegate]; self.closeButton = [self addCloseButtonWithAnimationDelegate:animationDelegate];
[self.closeButton setTintColor:self.contentColor ?:[UIColor whiteColor]]; [self.closeButton setTintColor:self.contentColor ?: [UIColor whiteColor]];
} else if (!closeButton && self.closeButton) { } else if (!closeButton && self.closeButton) {
[self.closeButton removeFromSuperview]; [self.closeButton removeFromSuperview];
self.closeButton = nil; self.closeButton = nil;
@ -241,17 +238,19 @@
}]; }];
} }
- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler {
[self setupWithMessage:message subMessage:subMessage color:nil actionMap:actionMap additionalData:additionalData];
}
- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler {
self.message = message; self.message = message;
self.subMessage = subMessage; self.subMessage = subMessage;
self.contentColor = color;
[MVMCoreDispatchUtility performBlockOnMainThread:^{ [MVMCoreDispatchUtility performBlockOnMainThread:^{
// Sets the string // Sets the string
self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:message subMessage:subMessage color:nil]; self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:message subMessage:subMessage color:color];
// Sets the color
if (color) {
[self.closeButton setTintColor:color];
}
// Sets the button // Sets the button
[self setupButtonWithButtonTitle:buttonTitle userActionHandler:userActionHandler]; [self setupButtonWithButtonTitle:buttonTitle userActionHandler:userActionHandler];
@ -284,36 +283,36 @@
#pragma mark - legacy inits #pragma mark - legacy inits
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData {
// No icon or close button. // No icon or close button.
if ([self init]) { if ([self init]) {
self.backgroundColor = color; self.backgroundColor = color;
[self setupViewWithLabelAndImage:nil topImage:nil]; [self setupViewWithLabelAndImage:nil topImage:nil];
[self setupWithMessage:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; [self setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData];
} }
return self; return self;
} }
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate { - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate {
// No main button. // No main button.
if ([self init]) { if ([self init]) {
self.backgroundColor = color; self.backgroundColor = color;
[self setupViewWithLabelAndImage:nil topImage:nil]; [self setupViewWithLabelAndImage:nil topImage:nil];
[self setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:nil userActionHandler:NULL];
[self setupCloseButton:closeButton animationDelegate:animationDelegate]; [self setupCloseButton:closeButton animationDelegate:animationDelegate];
[self setupWithMessage:message subMessage:subMessage buttonTitle:nil userActionHandler:NULL];
} }
return self; return self;
} }
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { - (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler {
// No icon or close button. Custom button action. // No icon or close button. Custom button action.
if ([self init]) { if ([self init]) {
self.backgroundColor = color; self.backgroundColor = color;
[self setupViewWithLabelAndImage:nil topImage:nil]; [self setupViewWithLabelAndImage:nil topImage:nil];
[self setupWithMessage:message subMessage:subMessage buttonTitle:buttonTitle userActionHandler:userActionHandler]; [self setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:buttonTitle userActionHandler:userActionHandler];
} }
return self; return self;
} }

View File

@ -47,9 +47,12 @@
// Can be subclassed for custom views. // Can be subclassed for custom views.
- (nonnull MVMCoreUITopAlertBaseView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor; - (nonnull MVMCoreUITopAlertBaseView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor;
// Get the background color based on the type /// Get the background color based on the type
- (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type; - (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type;
/// Get the content color based on the type
- (nonnull UIColor *)getContentColorForType:(nullable NSString *)type;
// Set the status bar color. Used for updating the status bar when the view changes. // Set the status bar color. Used for updating the status bar when the view changes.
- (void)setStatusBarColor:(nullable UIColor *)statusBarColor statusBarStyle:(UIStatusBarStyle)style; - (void)setStatusBarColor:(nullable UIColor *)statusBarColor statusBarStyle:(UIStatusBarStyle)style;

View File

@ -108,12 +108,20 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
- (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type { - (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type {
if ([type isEqualToString:ValueTypeError]) { if ([type isEqualToString:ValueTypeError]) {
return [UIColor mfPumpkinColor]; return [UIColor mvmOrange];
} else { } else {
return [UIColor mfShamrock]; return [UIColor mfShamrock];
} }
} }
- (nonnull UIColor *)getContentColorForType:(nullable NSString *)type {
if ([type isEqualToString:ValueTypeError]) {
return [UIColor blackColor];
} else {
return [UIColor whiteColor];
}
}
- (void)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler { - (void)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
self.animationDelegate = animationDelegate; self.animationDelegate = animationDelegate;
@ -127,6 +135,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
if (!statusBarColor) { if (!statusBarColor) {
statusBarColor = [UIColor whiteColor]; statusBarColor = [UIColor whiteColor];
} }
#warning This logic is incomplete, it is possible to show the wrong status bar color here if the background is yellow or pumpkin.
UIStatusBarStyle statusBarStyle = statusBarColor == [UIColor whiteColor] ? UIStatusBarStyleDefault : UIStatusBarStyleLightContent; UIStatusBarStyle statusBarStyle = statusBarColor == [UIColor whiteColor] ? UIStatusBarStyleDefault : UIStatusBarStyleLightContent;
[self setStatusBarColor:statusBarColor statusBarStyle:statusBarStyle]; [self setStatusBarColor:statusBarColor statusBarStyle:statusBarStyle];
[self showAlertView:view topAlertObject:topAlertObject completionHandler:completionHandler]; [self showAlertView:view topAlertObject:topAlertObject completionHandler:completionHandler];