merge
This commit is contained in:
commit
0a45d61eb7
@ -7,10 +7,16 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
01004F3022721C3800991ECC /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01004F2F22721C3800991ECC /* RadioButton.swift */; };
|
||||
0105618D224BBE7700E1557D /* FormValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618A224BBE7700E1557D /* FormValidator.swift */; };
|
||||
0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; };
|
||||
0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; };
|
||||
016A1071228122180009D605 /* HeadlineBodyTextButtonSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016A1070228122180009D605 /* HeadlineBodyTextButtonSwitch.swift */; };
|
||||
0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */; };
|
||||
01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */; };
|
||||
01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D902327ECE600EF99AA /* CornerLabels.swift */; };
|
||||
01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D922327ECFB00EF99AA /* ProgressBar.swift */; };
|
||||
01509D952327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D942327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift */; };
|
||||
017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */; };
|
||||
0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; };
|
||||
0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; };
|
||||
@ -24,8 +30,6 @@
|
||||
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; };
|
||||
9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; };
|
||||
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; };
|
||||
B8200E152280C4CF007245F4 /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E142280C4CF007245F4 /* ProgressBar.swift */; };
|
||||
B8200E192281DC1A007245F4 /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E182281DC1A007245F4 /* CornerLabels.swift */; };
|
||||
D206997721FB8A0B00CAE0DE /* MVMCoreUINavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D206997821FB8A0B00CAE0DE /* MVMCoreUINavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = D206997621FB8A0B00CAE0DE /* MVMCoreUINavigationController.m */; };
|
||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
|
||||
@ -46,6 +50,7 @@
|
||||
D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */; };
|
||||
D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* StandardFooterView.swift */; };
|
||||
D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2755D7A23689C7500485468 /* TableViewCell.swift */; };
|
||||
D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */; };
|
||||
D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */; };
|
||||
D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */; };
|
||||
@ -179,13 +184,14 @@
|
||||
D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */; };
|
||||
D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */; };
|
||||
D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B93236214AD00A9AEDC /* NavigationController.swift */; };
|
||||
D2B18B7F2360913400A9AEDC /* Control.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B7E2360913400A9AEDC /* Control.swift */; };
|
||||
D2B18B812360945C00A9AEDC /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B802360945C00A9AEDC /* View.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, ); }; };
|
||||
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; };
|
||||
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; };
|
||||
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; };
|
||||
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; };
|
||||
D2E1FADD2268B25E00AEFD8C /* MoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */; };
|
||||
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; };
|
||||
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; };
|
||||
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; };
|
||||
@ -197,10 +203,16 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
01004F2F22721C3800991ECC /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = "<group>"; };
|
||||
0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = "<group>"; };
|
||||
0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = "<group>"; };
|
||||
0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = "<group>"; };
|
||||
016A1070228122180009D605 /* HeadlineBodyTextButtonSwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyTextButtonSwitch.swift; sourceTree = "<group>"; };
|
||||
0116A4E4228B19640094F3ED /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = "<group>"; };
|
||||
01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeTableViewCell.swift; sourceTree = "<group>"; };
|
||||
01509D902327ECE600EF99AA /* CornerLabels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CornerLabels.swift; sourceTree = "<group>"; };
|
||||
01509D922327ECFB00EF99AA /* ProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = "<group>"; };
|
||||
01509D942327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyTextButtonSwitch.swift; sourceTree = "<group>"; };
|
||||
017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonLabel.swift; sourceTree = "<group>"; };
|
||||
0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = "<group>"; };
|
||||
0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = "<group>"; };
|
||||
0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = "<group>"; };
|
||||
@ -213,8 +225,6 @@
|
||||
0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = "<group>"; };
|
||||
9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = "<group>"; };
|
||||
948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = "<group>"; };
|
||||
B8200E142280C4CF007245F4 /* ProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = "<group>"; };
|
||||
B8200E182281DC1A007245F4 /* CornerLabels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerLabels.swift; sourceTree = "<group>"; };
|
||||
D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUINavigationController.h; sourceTree = "<group>"; };
|
||||
D206997621FB8A0B00CAE0DE /* MVMCoreUINavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUINavigationController.m; sourceTree = "<group>"; };
|
||||
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = "<group>"; };
|
||||
@ -235,6 +245,7 @@
|
||||
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>"; };
|
||||
D274CA322236A78900B01B62 /* StandardFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardFooterView.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>"; };
|
||||
D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EyebrowHeadlineBodyLink.swift; sourceTree = "<group>"; };
|
||||
D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFLoadImageView.swift; sourceTree = "<group>"; };
|
||||
@ -372,13 +383,14 @@
|
||||
D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreUIObject.swift; sourceTree = "<group>"; };
|
||||
D2B18B93236214AD00A9AEDC /* NavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = "<group>"; };
|
||||
D2B18B7E2360913400A9AEDC /* Control.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Control.swift; sourceTree = "<group>"; };
|
||||
D2B18B802360945C00A9AEDC /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.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>"; };
|
||||
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; 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>"; };
|
||||
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
|
||||
D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = "<group>"; };
|
||||
D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = "<group>"; };
|
||||
DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeftRightLabelView.swift; sourceTree = "<group>"; };
|
||||
@ -416,9 +428,9 @@
|
||||
D224798823142BF2003FCCF9 /* SwitchMolecules */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
01509D942327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift */,
|
||||
D22479892314445E003FCCF9 /* LabelSwitch.swift */,
|
||||
D224798B231450C8003FCCF9 /* HeadlineBodySwitch.swift */,
|
||||
016A1070228122180009D605 /* HeadlineBodyTextButtonSwitch.swift */,
|
||||
);
|
||||
path = SwitchMolecules;
|
||||
sourceTree = "<group>";
|
||||
@ -445,8 +457,8 @@
|
||||
D224798F2316A99F003FCCF9 /* LeftRightViews */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
01509D902327ECE600EF99AA /* CornerLabels.swift */,
|
||||
D224798823142BF2003FCCF9 /* SwitchMolecules */,
|
||||
B8200E182281DC1A007245F4 /* CornerLabels.swift */,
|
||||
);
|
||||
path = LeftRightViews;
|
||||
sourceTree = "<group>";
|
||||
@ -463,8 +475,9 @@
|
||||
D22479912316A9EF003FCCF9 /* Items */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2755D7A23689C7500485468 /* TableViewCell.swift */,
|
||||
01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */,
|
||||
D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */,
|
||||
D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */,
|
||||
D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */,
|
||||
D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */,
|
||||
);
|
||||
@ -504,6 +517,7 @@
|
||||
D29DF0CE21E404D4003B2FB9 /* MVMCoreUI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2B18B7D236090D500A9AEDC /* BaseClasses */,
|
||||
01C74D87224298E2009C25A3 /* FormUIHelpers */,
|
||||
D29DF31421ECECA7003B2FB9 /* SupportingFiles */,
|
||||
D29DF27021E79B2C003B2FB9 /* OtherHandlers */,
|
||||
@ -570,9 +584,11 @@
|
||||
D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */,
|
||||
D2A514662213885800345BFB /* StandardHeaderView.swift */,
|
||||
D274CA322236A78900B01B62 /* StandardFooterView.swift */,
|
||||
0116A4E4228B19640094F3ED /* RadioButtonModel.swift */,
|
||||
D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */,
|
||||
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */,
|
||||
0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */,
|
||||
017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */,
|
||||
);
|
||||
path = Molecules;
|
||||
sourceTree = "<group>";
|
||||
@ -696,10 +712,10 @@
|
||||
D29DF17D21E69E26003B2FB9 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
01509D922327ECFB00EF99AA /* ProgressBar.swift */,
|
||||
D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */,
|
||||
D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */,
|
||||
D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */,
|
||||
B8200E142280C4CF007245F4 /* ProgressBar.swift */,
|
||||
948DB67D2326DCD90011F916 /* MultiProgress.swift */,
|
||||
DBC4391622442196001AB423 /* CaretView.swift */,
|
||||
DBC4391722442197001AB423 /* DashLine.swift */,
|
||||
@ -735,6 +751,7 @@
|
||||
0198F7A22256A80A0066C936 /* MFRadioButton.m */,
|
||||
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */,
|
||||
0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */,
|
||||
01004F2F22721C3800991ECC /* RadioButton.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@ -852,6 +869,15 @@
|
||||
path = Strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D2B18B7D236090D500A9AEDC /* BaseClasses */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2B18B7E2360913400A9AEDC /* Control.swift */,
|
||||
D2B18B802360945C00A9AEDC /* View.swift */,
|
||||
);
|
||||
path = BaseClasses;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
@ -1018,13 +1044,16 @@
|
||||
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
|
||||
0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */,
|
||||
D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */,
|
||||
0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */,
|
||||
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */,
|
||||
D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */,
|
||||
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */,
|
||||
D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */,
|
||||
01004F3022721C3800991ECC /* RadioButton.swift in Sources */,
|
||||
D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */,
|
||||
D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */,
|
||||
D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */,
|
||||
D2B18B7F2360913400A9AEDC /* Control.swift in Sources */,
|
||||
D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */,
|
||||
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */,
|
||||
D224798C231450C8003FCCF9 /* HeadlineBodySwitch.swift in Sources */,
|
||||
@ -1041,15 +1070,17 @@
|
||||
D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */,
|
||||
D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */,
|
||||
D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */,
|
||||
D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */,
|
||||
D29DF25421E6A177003B2FB9 /* MFMdnTextField.m in Sources */,
|
||||
B8200E152280C4CF007245F4 /* ProgressBar.swift in Sources */,
|
||||
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
|
||||
D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */,
|
||||
DBEFFA04225A829700230692 /* Label.swift in Sources */,
|
||||
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */,
|
||||
01509D952327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift in Sources */,
|
||||
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
|
||||
0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */,
|
||||
D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */,
|
||||
D2B18B812360945C00A9AEDC /* View.swift in Sources */,
|
||||
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
|
||||
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
|
||||
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */,
|
||||
@ -1059,8 +1090,8 @@
|
||||
0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */,
|
||||
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */,
|
||||
D22479962316AF6E003FCCF9 /* HeadlineBodyTextButton.swift in Sources */,
|
||||
D2E1FADD2268B25E00AEFD8C /* MoleculeTableViewCell.swift in Sources */,
|
||||
D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */,
|
||||
017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */,
|
||||
D29DF18121E69E50003B2FB9 /* MFView.m in Sources */,
|
||||
D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */,
|
||||
D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */,
|
||||
@ -1075,7 +1106,6 @@
|
||||
D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */,
|
||||
D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */,
|
||||
D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */,
|
||||
016A1071228122180009D605 /* HeadlineBodyTextButtonSwitch.swift in Sources */,
|
||||
D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */,
|
||||
D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */,
|
||||
D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */,
|
||||
@ -1112,11 +1142,13 @@
|
||||
D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */,
|
||||
D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */,
|
||||
D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */,
|
||||
B8200E192281DC1A007245F4 /* CornerLabels.swift in Sources */,
|
||||
D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */,
|
||||
01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */,
|
||||
0105618D224BBE7700E1557D /* FormValidator.swift in Sources */,
|
||||
01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */,
|
||||
D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */,
|
||||
D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */,
|
||||
01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */,
|
||||
D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
@ -64,7 +64,7 @@ import UIKit
|
||||
primaryButton?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 42
|
||||
}
|
||||
|
||||
|
||||
@ -140,7 +140,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
|
||||
return UIStackView.Alignment.leading;
|
||||
}
|
||||
|
||||
public static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 10
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,13 +13,15 @@
|
||||
#import "MFStyler.h"
|
||||
#import "UIColor+MFConvenience.h"
|
||||
#import <MVMCoreUI/MVMCoreUI-Swift.h>
|
||||
|
||||
@import MVMCore.MVMCoreDispatchUtility;
|
||||
@import MVMCore.MVMCoreGetterUtility;
|
||||
@import MVMCore.NSDictionary_MFConvenience;
|
||||
|
||||
@interface PrimaryButton() <FormValidationProtocol>
|
||||
@interface PrimaryButton() <FormValidationEnableDisableProtocol>
|
||||
|
||||
@property (nonatomic) BOOL validationRequired;
|
||||
@property (nonatomic, strong) NSArray *requiredGroupsList;
|
||||
@property (nonatomic) BOOL smallButton;
|
||||
@property (assign, nonatomic) BOOL tinyButton;
|
||||
@property (nonatomic) CGFloat sizeForSizing;
|
||||
@ -666,6 +668,9 @@
|
||||
}
|
||||
|
||||
- (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
|
||||
|
||||
self.validationRequired = [json boolForKey:@"validationRequired"];
|
||||
self.requiredGroupsList = [json array:@"requiredGroups"];
|
||||
[FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol];
|
||||
|
||||
self.primaryButtonType = PrimaryButtonTypeCustom;
|
||||
@ -696,7 +701,6 @@
|
||||
if ((color = [json string:@"disabledBorderColor"])) {
|
||||
self.disabledBorderColor = [UIColor mfGetColorForHex:color];
|
||||
}
|
||||
self.validationRequired = [json boolForKey:@"validationRequired"];
|
||||
|
||||
NSString *size = [json string:@"size"];
|
||||
if ([size isEqualToString:@"small"]) {
|
||||
@ -773,7 +777,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - FormValidationProtocol
|
||||
#pragma mark - FormValidationEnableDisableProtocol
|
||||
|
||||
- (BOOL)isValidationRequired {
|
||||
return self.validationRequired;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)requiredGroups {
|
||||
return self.requiredGroupsList;
|
||||
}
|
||||
|
||||
- (void)enableField:(BOOL)enable {
|
||||
if (!self.validationRequired) {
|
||||
|
||||
@ -46,7 +46,8 @@
|
||||
// To set the placeholder and text
|
||||
@property (nullable, weak, nonatomic) NSString *text;
|
||||
@property (nullable, weak, nonatomic) NSString *formText;
|
||||
@property (nullable, weak, nonatomic) NSString *fieldKey;
|
||||
@property (nullable, strong, nonatomic) NSString *fieldKey;
|
||||
@property (nullable, strong, nonatomic) NSString *groupName;
|
||||
|
||||
@property (nullable, weak, nonatomic) NSString *placeholder; // will move out in Feb release
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
@import MVMCore.NSDictionary_MFConvenience;
|
||||
@import MVMCore.MVMCoreJSONConstants;
|
||||
|
||||
@interface MFTextField() <FormValidationProtocol>
|
||||
@interface MFTextField() <FormValidationFormFieldProtocol>
|
||||
|
||||
@property (strong, nonatomic) UIColor *customPlaceHolderColor;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *separatorHeightConstraint;
|
||||
@ -317,12 +317,14 @@
|
||||
if (string.length > 0) {
|
||||
self.errMessage = string;
|
||||
}
|
||||
|
||||
|
||||
// key used to send text value to server
|
||||
string = [map string:KeyFieldKey];
|
||||
if (string.length > 0) {
|
||||
self.fieldKey = string;
|
||||
}
|
||||
|
||||
self.groupName = [map string:@"groupName"];
|
||||
|
||||
string = [map string:KeyType];
|
||||
if ([string isEqualToString:@"dropDown"]) {
|
||||
@ -586,5 +588,9 @@
|
||||
- (nullable id)formFieldValue {
|
||||
return self.text;
|
||||
}
|
||||
|
||||
|
||||
- (NSString * _Nullable)formFieldGroupName {
|
||||
return self.groupName;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -19,7 +19,8 @@ import MVMCore
|
||||
// Form Validation
|
||||
var isRequired = false
|
||||
var fieldKey: String?
|
||||
var delegateObject: DelegateObject?
|
||||
var groupName: String?
|
||||
var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
public static let defaultHeightWidth: CGFloat = 18.0
|
||||
|
||||
@ -104,12 +105,8 @@ import MVMCore
|
||||
layoutIfNeeded()
|
||||
shapeLayer?.removeAllAnimations()
|
||||
|
||||
updateCheckboxUI(isSelected: isSelected, isAnimated: isAnimated)
|
||||
|
||||
if let delegate = delegateObject as? FormValidationProtocol {
|
||||
delegate.formValidatorModel?()?.enableByValidation()
|
||||
}
|
||||
|
||||
updateCheckboxUI(isSelected: isSelected, isAnimated: isAnimated)
|
||||
FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol)
|
||||
updateAccessibilityLabel()
|
||||
}
|
||||
}
|
||||
@ -211,7 +208,6 @@ import MVMCore
|
||||
|
||||
/// This will toggle the state of the Checkbox and execute the actionBlock if provided.
|
||||
public func toggleAndAction() {
|
||||
|
||||
isSelected.toggle()
|
||||
actionBlock?()
|
||||
}
|
||||
@ -308,8 +304,9 @@ import MVMCore
|
||||
/// Adjust accessibility label based on state of Checkbox.
|
||||
func updateAccessibilityLabel() {
|
||||
// Attention: This needs to be addressed with the accessibility team.
|
||||
// NOTE: Currently emptying description part of MVMCoreUICheckBox accessibility label to avoid crashing!
|
||||
if let state = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "checkbox_checked_state" : "checkbox_unchecked_state") {
|
||||
accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "checkbox_desc_state") ?? "%@", state)
|
||||
accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "checkbox_desc_state") ?? "%@%@", "", state)
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,7 +405,8 @@ import MVMCore
|
||||
FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol)
|
||||
|
||||
guard let dictionary = json else { return }
|
||||
|
||||
|
||||
groupName = dictionary.optionalStringForKey("groupName")
|
||||
if let fieldKey = dictionary[KeyFieldKey] as? String {
|
||||
self.fieldKey = fieldKey
|
||||
}
|
||||
@ -462,7 +460,11 @@ import MVMCore
|
||||
}
|
||||
|
||||
// MARK:- FormValidationProtocol
|
||||
extension Checkbox: FormValidationProtocol {
|
||||
extension Checkbox: FormValidationFormFieldProtocol {
|
||||
|
||||
public func formFieldGroupName() -> String? {
|
||||
return groupName
|
||||
}
|
||||
|
||||
public func isValidField() -> Bool {
|
||||
return isRequired ? isSelected : true
|
||||
|
||||
@ -37,10 +37,15 @@ public typealias ActionBlock = () -> ()
|
||||
return !text.isEmpty || !attributedText.string.isEmpty
|
||||
}
|
||||
|
||||
public var getRange: NSRange {
|
||||
return NSRange(location: 0, length: text?.count ?? 0)
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Multi-Action Text
|
||||
//------------------------------------------------------
|
||||
|
||||
/// Data store of the tappable ranges of the text.
|
||||
public var clauses: [ActionableClause] = [] {
|
||||
didSet {
|
||||
isUserInteractionEnabled = !clauses.isEmpty
|
||||
@ -112,6 +117,15 @@ public typealias ActionBlock = () -> ()
|
||||
standardFontSize = size
|
||||
}
|
||||
|
||||
/// Convenience to init Label with a link comprised of range, actionMap and delegateObject
|
||||
@objc convenience public init(text: String, range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
self.init()
|
||||
self.text = text
|
||||
if let actionBlock = createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
setTextLinkState(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Factory Functions
|
||||
//------------------------------------------------------
|
||||
@ -307,8 +321,9 @@ public typealias ActionBlock = () -> ()
|
||||
guard let actionLabel = label as? Label else { continue }
|
||||
|
||||
actionLabel.addActionAttributes(range: range, string: attributedString)
|
||||
let actionBlock = actionLabel.createActionBlockFrom(actionMap: attribute, additionalData: additionalData, delegateObject: delegate)
|
||||
actionLabel.appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
if let actionBlock = actionLabel.createActionBlockFor(actionMap: attribute, additionalData: additionalData, delegateObject: delegate) {
|
||||
actionLabel.appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
default:
|
||||
continue
|
||||
@ -483,7 +498,7 @@ public typealias ActionBlock = () -> ()
|
||||
}
|
||||
|
||||
/// Call to detect in the attributedText contains an NSTextAttachment.
|
||||
func textContainsTextAttachment() -> Bool {
|
||||
func containsTextAttachment() -> Bool {
|
||||
|
||||
guard let attributedText = attributedText else { return false }
|
||||
|
||||
@ -588,7 +603,7 @@ extension Label {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Multi-Action Functionality
|
||||
// MARK: - Multi-Link Functionality
|
||||
extension Label {
|
||||
|
||||
/// Applied to existing text. Removes underlines of tappable links and assoated actionable clauses.
|
||||
@ -607,15 +622,17 @@ extension Label {
|
||||
clauses = []
|
||||
}
|
||||
|
||||
public func createActionBlockFrom(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) -> ActionBlock {
|
||||
public func createActionBlockFor(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) -> ActionBlock? {
|
||||
return { [weak self] in
|
||||
if let wSelf = self, (delegateObject as? MVMCoreUIDelegateObject)?.buttonDelegate?.button?(wSelf, shouldPerformActionWithMap: actionMap, additionalData: additionalData) ?? true {
|
||||
guard let self = self else { return }
|
||||
|
||||
if (delegateObject as? MVMCoreUIDelegateObject)?.buttonDelegate?.button?(self, shouldPerformActionWithMap: actionMap, additionalData: additionalData) ?? true {
|
||||
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addActionAttributes(range: NSRange, string: NSMutableAttributedString?) {
|
||||
private func addActionAttributes(range: NSRange, string: NSMutableAttributedString?) {
|
||||
|
||||
guard let string = string else { return }
|
||||
string.addAttributes([NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue], range: range)
|
||||
@ -639,8 +656,7 @@ extension Label {
|
||||
*/
|
||||
@objc public func addTappableLinkAttribute(range: NSRange, actionBlock: @escaping ActionBlock) {
|
||||
|
||||
setActionAttributes(range: range)
|
||||
appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
setTextLinkState(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -654,15 +670,35 @@ extension Label {
|
||||
*/
|
||||
@objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
|
||||
if let actionBlock = createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
setTextLinkState(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the entire text into a link. All characters will be underlined and the intrinsic bounds will respond to tap.
|
||||
@objc public func makeTextButton(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
|
||||
if let actionBlock = createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
setTextLinkState(range: getRange, actionBlock: actionBlock)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the entire text into a link. All characters will be underlined and the intrinsic bounds will respond to tap.
|
||||
@objc public func makeTextButton(actionBlock: @escaping ActionBlock) {
|
||||
|
||||
setTextLinkState(range: getRange, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
/// Underlines the tappable region and stores the tap logic for interation.
|
||||
private func setTextLinkState(range: NSRange, actionBlock: @escaping ActionBlock) {
|
||||
|
||||
setActionAttributes(range: range)
|
||||
let actionBlock = createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
@objc private func textLinkTapped(_ gesture: UITapGestureRecognizer) {
|
||||
|
||||
for clause in clauses {
|
||||
|
||||
// This determines if we tapped on the desired range of text.
|
||||
if let range = clause.range, gesture.didTapAttributedTextInLabel(self, inRange: range) {
|
||||
clause.performAction()
|
||||
@ -686,9 +722,33 @@ extension UITapGestureRecognizer {
|
||||
let textContainer = abstractContainer.0
|
||||
let layoutManager = abstractContainer.1
|
||||
|
||||
let indexOfGlyph = layoutManager.glyphIndex(for: location(in: label), in: textContainer)
|
||||
let tapLocation = location(in: label)
|
||||
let indexOfGlyph = layoutManager.glyphIndex(for: tapLocation, in: textContainer)
|
||||
let intrinsicWidth = label.intrinsicContentSize.width
|
||||
|
||||
return NSLocationInRange(indexOfGlyph, targetRange)
|
||||
// Assert that tapped occured within acceptable bounds based on alignment.
|
||||
switch label.textAlignment {
|
||||
case .right:
|
||||
if tapLocation.x < label.bounds.width - intrinsicWidth {
|
||||
return false
|
||||
}
|
||||
case .center:
|
||||
let halfBounds = label.bounds.width / 2
|
||||
let halfIntrinsicWidth = intrinsicWidth / 2
|
||||
|
||||
if tapLocation.x > halfBounds + halfIntrinsicWidth {
|
||||
return false
|
||||
} else if tapLocation.x < halfBounds - halfIntrinsicWidth {
|
||||
return false
|
||||
}
|
||||
default: // Left align
|
||||
if tapLocation.x > intrinsicWidth {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Affirms that the tap occured in the desired rect of provided by the target range.
|
||||
return layoutManager.boundingRect(forGlyphRange: targetRange, in: textContainer).contains(tapLocation) && NSLocationInRange(indexOfGlyph, targetRange)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -207,7 +207,7 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
||||
|
||||
@objc public func setActionMap(_ actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
|
||||
actionBlock = label?.createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
actionBlock = label?.createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
@ -377,7 +377,7 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
||||
actionText = actionMap?.optionalStringForKey(KeyTitle)
|
||||
backText = actionMap?.optionalStringForKey(KeyTitlePostfix)
|
||||
text = getTextFromStringComponents()
|
||||
actionBlock = label?.createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
actionBlock = label?.createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
setLabelAttributes()
|
||||
}
|
||||
|
||||
|
||||
@ -215,7 +215,7 @@ import UIKit
|
||||
pinEdges(.all)
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return json?.optionalCGFloatForKey("height") ?? 0
|
||||
}
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
static const CGFloat FaultTolerance = 20.f;
|
||||
static const CGFloat CheckBoxHeightWidth = 18.0;
|
||||
|
||||
@interface MVMCoreUICheckBox () <FormValidationProtocol, MVMCoreUIMoleculeViewProtocol>
|
||||
@interface MVMCoreUICheckBox () <FormValidationFormFieldProtocol, MVMCoreUIMoleculeViewProtocol>
|
||||
|
||||
@property (nonatomic, readwrite) BOOL isSelected;
|
||||
@property (weak, nonatomic) UIView *checkedSquare;
|
||||
@ -42,7 +42,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0;
|
||||
|
||||
@property (nonatomic) BOOL isRequired;
|
||||
@property (nullable, strong, nonatomic) NSString *fieldKey;
|
||||
@property (nullable, strong, nonatomic) DelegateObject *delegate;
|
||||
@property (nullable, strong, nonatomic) MVMCoreUIDelegateObject *delegateObject;
|
||||
|
||||
@end
|
||||
|
||||
@ -61,7 +61,8 @@ static const CGFloat CheckBoxHeightWidth = 18.0;
|
||||
- (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
|
||||
|
||||
[FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol];
|
||||
self.delegate = delegateObject;
|
||||
|
||||
self.delegateObject = delegateObject;
|
||||
self.fieldKey = [json stringForKey:KeyFieldKey];
|
||||
self.isRequired = [json boolForKey:KeyRequired];
|
||||
|
||||
@ -347,10 +348,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0;
|
||||
[self.checkMark updateCheckSelected:NO animated:animated];
|
||||
}
|
||||
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(formValidationProtocol)] && [[self.delegate performSelector:@selector(formValidationProtocol)] respondsToSelector:@selector(formValidatorModel)]) {
|
||||
FormValidator *formValidator = [[self.delegate performSelector:@selector(formValidationProtocol)] performSelector:@selector(formValidatorModel)];
|
||||
[formValidator enableByValidation];
|
||||
}
|
||||
[FormValidator enableByValidationWithDelegate:self.delegateObject.formValidationProtocol];
|
||||
}
|
||||
|
||||
- (void)setColor:(nullable UIColor *)color forState:(UIControlState)state {
|
||||
|
||||
@ -24,6 +24,7 @@ typedef void(^ValueChangeBlock)(void);
|
||||
|
||||
@property (nonatomic) BOOL shouldTouchToSwitch;
|
||||
@property (nullable, copy, nonatomic) ValueChangeBlock valueChangedBlock;
|
||||
@property (nullable, copy, nonatomic) ValueChangeBlock actionBlock;
|
||||
|
||||
+ (nonnull instancetype)mvmSwitchDefault;
|
||||
+ (nonnull instancetype)mvmSwitchDefaultWithValueChangeBlock:(nullable ValueChangeBlock)block;
|
||||
|
||||
@ -22,7 +22,7 @@ const CGFloat SwitchKnobWidth = 20;
|
||||
const CGFloat SwitchKnobHeight = 20;
|
||||
const CGFloat SwitchShakeIntensity = 2;
|
||||
|
||||
@interface MVMCoreUISwitch () <FormValidationProtocol, MVMCoreUIViewConstrainingProtocol>
|
||||
@interface MVMCoreUISwitch () <FormValidationFormFieldProtocol, MVMCoreUIViewConstrainingProtocol>
|
||||
|
||||
@property (weak, nonatomic) UIView *baseView;
|
||||
@property (weak, nonatomic) UIView *knobView;
|
||||
@ -145,7 +145,8 @@ const CGFloat SwitchShakeIntensity = 2;
|
||||
|
||||
- (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
|
||||
self.json = json;
|
||||
|
||||
self.delegate = delegateObject;
|
||||
|
||||
[FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol];
|
||||
|
||||
NSString *color = [json string:@"onTintColor"];
|
||||
@ -169,6 +170,17 @@ const CGFloat SwitchShakeIntensity = 2;
|
||||
}
|
||||
|
||||
[self setState:[json boolForKey:@"state"] animated:false];
|
||||
|
||||
NSDictionary *actionMap = [json dict:@"actionMap"];
|
||||
if (actionMap) {
|
||||
[self addTarget:self action:@selector(addCustomAction) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addCustomAction {
|
||||
if (self.actionBlock) {
|
||||
self.actionBlock();
|
||||
}
|
||||
}
|
||||
|
||||
+ (CGFloat)estimatedHeightForRow:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject {
|
||||
|
||||
@ -73,7 +73,7 @@ import Foundation
|
||||
trackTintColor = UIColor.mfLightSilver()
|
||||
}
|
||||
|
||||
public static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 8
|
||||
}
|
||||
}
|
||||
|
||||
135
MVMCoreUI/Atoms/Views/RadioButton.swift
Normal file
135
MVMCoreUI/Atoms/Views/RadioButton.swift
Normal file
@ -0,0 +1,135 @@
|
||||
//
|
||||
// RadioButton.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 4/25/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers public class RadioButton: Control, FormValidationFormFieldProtocol {
|
||||
|
||||
var diameter: CGFloat = 30 {
|
||||
didSet {
|
||||
widthConstraint?.constant = diameter
|
||||
}
|
||||
}
|
||||
var enabledColor = UIColor.black
|
||||
var disabledColor = UIColor.mfSilver()
|
||||
|
||||
var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
var fieldKey: String?
|
||||
var formValue: Bool?
|
||||
var isRequired: Bool = false
|
||||
|
||||
var widthConstraint: NSLayoutConstraint?
|
||||
var heightConstraint: NSLayoutConstraint?
|
||||
|
||||
lazy var radioGroupName: String? = {
|
||||
[unowned self] in
|
||||
return json?.optionalStringForKey("radioGroupName") ?? json?.optionalStringForKey("fieldKey")
|
||||
}()
|
||||
|
||||
lazy var radioButtonModel: RadioButtonModel? = {
|
||||
[unowned self] in
|
||||
if let radioGroupName = radioGroupName,
|
||||
let radioButtonModel = delegateObject?.formValidationProtocol?.formValidatorModel?()?.radioButtonsModelByGroup[radioGroupName] {
|
||||
return radioButtonModel
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
|
||||
open override func draw(_ rect: CGRect) {
|
||||
guard let context = UIGraphicsGetCurrentContext() else { return }
|
||||
let color = isEnabled ? enabledColor.cgColor : disabledColor.cgColor
|
||||
layer.cornerRadius = bounds.width * 0.5
|
||||
layer.borderColor = color
|
||||
layer.borderWidth = bounds.width * 0.0333
|
||||
if isSelected {
|
||||
// Space around inner circle is 1/5 the size
|
||||
context.addEllipse(in: CGRect(x: bounds.width*0.2, y: bounds.height*0.2, width: bounds.width*0.6, height: bounds.height*0.6))
|
||||
context.setFillColor(color)
|
||||
context.fillPath()
|
||||
}
|
||||
}
|
||||
|
||||
/// The action performed when tapped.
|
||||
func tapAction() {
|
||||
if let radioButtonModel = radioButtonModel {
|
||||
radioButtonModel.selected(self)
|
||||
} else {
|
||||
isSelected = !isSelected
|
||||
}
|
||||
FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol)
|
||||
setNeedsDisplay()
|
||||
}
|
||||
|
||||
public func isValidField() -> Bool {
|
||||
return isSelected
|
||||
}
|
||||
|
||||
public func formFieldName() -> String? {
|
||||
return json?.optionalStringForKey("fieldKey")
|
||||
}
|
||||
|
||||
public func formFieldGroupName() -> String? {
|
||||
return json?.optionalStringForKey("groupName")
|
||||
}
|
||||
|
||||
public func formFieldValue() -> Any? {
|
||||
return isSelected
|
||||
}
|
||||
|
||||
// MARK: - MVMViewProtocol
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
backgroundColor = .white
|
||||
clipsToBounds = true
|
||||
widthConstraint = widthAnchor.constraint(equalToConstant: 30)
|
||||
widthConstraint?.isActive = true
|
||||
heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1)
|
||||
heightConstraint?.isActive = true
|
||||
|
||||
addTarget(self, action: #selector(tapAction), for: .touchUpInside)
|
||||
isAccessibilityElement = true
|
||||
accessibilityTraits = .button
|
||||
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreUIViewConstrainingProtocol
|
||||
extension RadioButton: MVMCoreUIViewConstrainingProtocol {
|
||||
public func needsToBeConstrained() -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||
extension RadioButton {
|
||||
|
||||
@objc open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
|
||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||
|
||||
// Configure class properties with JSON values
|
||||
guard let jsonDictionary = json else {
|
||||
return
|
||||
}
|
||||
|
||||
fieldKey = jsonDictionary.optionalStringForKey("fieldKey")
|
||||
isRequired = jsonDictionary.boolForKey("required")
|
||||
self.delegateObject = delegateObject
|
||||
|
||||
let radioButtonModel = RadioButtonModel.setupForRadioButtonGroup(radioButton: self,
|
||||
formValidator: delegateObject?.formValidationProtocol?.formValidatorModel?())
|
||||
FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formValidationProtocol)
|
||||
}
|
||||
|
||||
public override func reset() {
|
||||
super.reset()
|
||||
backgroundColor = .white
|
||||
}
|
||||
}
|
||||
62
MVMCoreUI/BaseClasses/Control.swift
Normal file
62
MVMCoreUI/BaseClasses/Control.swift
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// Control.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 10/23/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
public class Control: UIControl {
|
||||
var json: [AnyHashable: Any]?
|
||||
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: .zero)
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
init() {
|
||||
super.init(frame: .zero)
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
public required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
public func initialSetup() {
|
||||
if !initialSetupPerformed {
|
||||
initialSetupPerformed = true
|
||||
setupView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Control: MVMCoreViewProtocol {
|
||||
public func updateView(_ size: CGFloat) {
|
||||
}
|
||||
|
||||
/// Will be called only once.
|
||||
public func setupView() {
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
insetsLayoutMarginsFromSafeArea = false
|
||||
}
|
||||
}
|
||||
|
||||
extension Control: MVMCoreUIMoleculeViewProtocol {
|
||||
public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
|
||||
self.json = json
|
||||
|
||||
if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) {
|
||||
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
|
||||
}
|
||||
}
|
||||
|
||||
public func reset() {
|
||||
backgroundColor = .clear
|
||||
}
|
||||
}
|
||||
61
MVMCoreUI/BaseClasses/View.swift
Normal file
61
MVMCoreUI/BaseClasses/View.swift
Normal file
@ -0,0 +1,61 @@
|
||||
//
|
||||
// View.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 10/23/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class View: UIView {
|
||||
open var json: [AnyHashable: Any]?
|
||||
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: .zero)
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
public init() {
|
||||
super.init(frame: .zero)
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
public required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
public func initialSetup() {
|
||||
if !initialSetupPerformed {
|
||||
initialSetupPerformed = true
|
||||
setupView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension View: MVMCoreViewProtocol {
|
||||
open func updateView(_ size: CGFloat) {}
|
||||
|
||||
/// Will be called only once.
|
||||
open func setupView() {
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
insetsLayoutMarginsFromSafeArea = false
|
||||
}
|
||||
}
|
||||
|
||||
extension View: MVMCoreUIMoleculeViewProtocol {
|
||||
open func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
|
||||
self.json = json
|
||||
|
||||
if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) {
|
||||
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
|
||||
}
|
||||
}
|
||||
|
||||
open func reset() {
|
||||
backgroundColor = .clear
|
||||
}
|
||||
}
|
||||
@ -214,14 +214,16 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController {
|
||||
/// Subclass for a top view.
|
||||
open func viewForTop() -> UIView {
|
||||
let view = MVMCoreUICommonViewsUtility.commonView()
|
||||
view.heightAnchor.constraint(equalToConstant: 0).isActive = true
|
||||
// Small height is needed to stop apple from adding padding for grouped tables when no header.
|
||||
view.heightAnchor.constraint(equalToConstant: 1).isActive = true
|
||||
return view
|
||||
}
|
||||
|
||||
/// Subclass for a bottom view.
|
||||
open func viewForBottom() -> UIView {
|
||||
// Default spacing is standard when no buttons.
|
||||
let view = MVMCoreUICommonViewsUtility.commonView()
|
||||
view.heightAnchor.constraint(equalToConstant: 0).isActive = true
|
||||
view.heightAnchor.constraint(equalToConstant: PaddingDefaultVerticalSpacing).isActive = true
|
||||
return view
|
||||
}
|
||||
|
||||
|
||||
61
MVMCoreUI/BaseControllers/ViewController.swift
Normal file
61
MVMCoreUI/BaseControllers/ViewController.swift
Normal file
@ -0,0 +1,61 @@
|
||||
//
|
||||
// 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?
|
||||
|
||||
// MARK: - Response handling
|
||||
public func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool {
|
||||
pageType = loadObject.pageType
|
||||
self.loadObject = loadObject
|
||||
|
||||
// Verifies all modules needed are loaded.
|
||||
return MFViewController.verifyRequiredModulesLoaded(for: loadObject, error: error)
|
||||
}
|
||||
|
||||
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}), index != NSNotFound {
|
||||
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 newDataBuildScreen() {
|
||||
// TODO- tell navigation object to update with model
|
||||
|
||||
}
|
||||
|
||||
open func initialLoad() {
|
||||
}
|
||||
|
||||
open func updateViews() {
|
||||
}
|
||||
|
||||
override open func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
//
|
||||
// MVMCoreUINavigationController.h
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 1/25/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
@class SeparatorView;
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MVMCoreUINavigationController : UINavigationController
|
||||
|
||||
// Convenience getter
|
||||
+ (nullable instancetype)navigationController;
|
||||
|
||||
// Returns a navigation controller with the mvm styling. Also sets the navigation controller in the appropriate handlers.
|
||||
+ (nullable instancetype)setupNavigationController;
|
||||
|
||||
// Returns a navigation controller with the mvm styling. Also sets the navigation controller in the appropriate handlers. Adds the default loading overlay screen as well.
|
||||
+ (nullable instancetype)setupWithNavigationControllerAsMainController;
|
||||
|
||||
// Separator at the bottom of the navigation bar used for styling.
|
||||
@property (nullable, weak, nonatomic) SeparatorView *separatorView;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,52 +0,0 @@
|
||||
//
|
||||
// MVMCoreUINavigationController.m
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 1/25/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MVMCoreUINavigationController.h"
|
||||
#import "UIColor+MFConvenience.h"
|
||||
#import "SeparatorView.h"
|
||||
#import "MFFonts.h"
|
||||
#import "MFSizeObject.h"
|
||||
#import "MVMCoreUISession.h"
|
||||
@import MVMCore.MVMCoreActionUtility;
|
||||
@import MVMCore.MVMCoreNavigationHandler;
|
||||
@interface MVMCoreUINavigationController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation MVMCoreUINavigationController
|
||||
|
||||
+ (nullable instancetype)navigationController {
|
||||
return [MVMCoreActionUtility initializerClassCheck:[MVMCoreUISession sharedGlobal].navigationController classToVerify:self];
|
||||
}
|
||||
|
||||
+ (nullable instancetype)setupNavigationController {
|
||||
MVMCoreUINavigationController *navigationController = [[MVMCoreUINavigationController alloc] init];
|
||||
[UIColor mfSetBackgroundColorForNavigationBar:[UIColor whiteColor] navigationBar:navigationController.navigationBar transparent:NO];
|
||||
[navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
|
||||
navigationController.navigationBar.translucent = NO;
|
||||
navigationController.navigationBar.opaque = YES;
|
||||
navigationController.navigationBar.tintColor = [UIColor blackColor];
|
||||
navigationController.separatorView = [SeparatorView separatorAddToView:navigationController.navigationBar position:SeparatorPositionBot withHorizontalPadding:0];
|
||||
[navigationController.separatorView setAsLight];
|
||||
[navigationController.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[MFFonts mfFont75Bd:[[MFSizeObject sizeObjectWithStandardSize:14 standardiPadPortraitSize:16 iPadProLandscapeSize:18] getValueBasedOnScreenSize]]}];
|
||||
|
||||
// Set standard
|
||||
[MVMCoreUISession sharedGlobal].navigationController = navigationController;
|
||||
[MVMCoreNavigationHandler sharedNavigationHandler].navigationController = navigationController;
|
||||
[MVMCoreNavigationHandler sharedNavigationHandler].viewControllerToPresentOn = navigationController;
|
||||
|
||||
return navigationController;
|
||||
}
|
||||
|
||||
+ (nullable instancetype)setupWithNavigationControllerAsMainController {
|
||||
MVMCoreUINavigationController *navigationController = [self setupNavigationController];
|
||||
[[MVMCoreUISession sharedGlobal] setupAsStandardLoadViewDelegate:navigationController];
|
||||
return navigationController;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -10,18 +10,32 @@ import Foundation
|
||||
|
||||
@objc public protocol FormValidationProtocol: NSObjectProtocol {
|
||||
|
||||
// Getter method to get the FormValidator form the delegate (Mostly from the parent View Controller)
|
||||
// Getter method to get the FormValidator from the delegate (Mostly from the parent View Controller)
|
||||
@objc optional func formValidatorModel() -> FormValidator?
|
||||
}
|
||||
|
||||
@objc public protocol FormValidationFormFieldProtocol: FormValidationProtocol {
|
||||
// Used to check the validity of the field. For example, to enable/disable the primary button.
|
||||
@objc func isValidField() -> Bool
|
||||
|
||||
// Used to check the validity of the field, to enable/disable the primary button.
|
||||
@objc optional func isValidField() -> Bool
|
||||
// The Field name key value pair for sending to server
|
||||
@objc func formFieldName() -> String?
|
||||
|
||||
// Returns the group name for validation. The class should always return a value.
|
||||
@objc func formFieldGroupName() -> String?
|
||||
|
||||
// The Field value key value pair for sending to server
|
||||
@objc func formFieldValue() -> Any?
|
||||
}
|
||||
|
||||
@objc public protocol FormValidationEnableDisableProtocol: FormValidationProtocol {
|
||||
|
||||
// Returns true if the button needs to be enabled/disabled based on the validation
|
||||
@objc func isValidationRequired() -> Bool
|
||||
|
||||
// Based on the isValidField(), the fields which needs to be enabled can call this method
|
||||
@objc optional func enableField(_ enable: Bool)
|
||||
|
||||
// The Field name key value pair for sending to server
|
||||
@objc optional func formFieldName() -> String?
|
||||
|
||||
// The Field value key value pair for sending to server
|
||||
@objc optional func formFieldValue() -> Any?
|
||||
// Returns the list of field keys required to enable/disable
|
||||
@objc optional func requiredGroups() -> [String]?
|
||||
}
|
||||
|
||||
@ -16,13 +16,10 @@ import Foundation
|
||||
@objc func getFormParams() -> [String: Any] {
|
||||
var extraParam: [String: Any] = [:]
|
||||
MVMCoreDispatchUtility.performSyncBlock(onMainThread: {
|
||||
for molecule in self.molecules {
|
||||
if let formFieldName = molecule.formFieldName,
|
||||
let formFieldValue = molecule.formFieldValue,
|
||||
let fieldName = formFieldName(),
|
||||
let fieldValue = formFieldValue() {
|
||||
|
||||
extraParam[fieldName] = fieldValue
|
||||
for molecule in self.fieldMolecules {
|
||||
if let formFieldName = molecule.formFieldName(),
|
||||
let formFieldValue = molecule.formFieldValue() {
|
||||
extraParam[formFieldName] = formFieldValue
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -8,52 +8,79 @@
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import MVMCore
|
||||
|
||||
@objcMembers public class FormValidator: NSObject {
|
||||
|
||||
var delegate: FormValidationProtocol?
|
||||
var molecules: [UIView & FormValidationProtocol] = []
|
||||
var extraValidationBlock: (() -> Bool)?
|
||||
var dummyGroupName = "dummyGroupName"
|
||||
weak var delegate: FormValidationProtocol?
|
||||
var fieldMolecules: [FormValidationFormFieldProtocol] = []
|
||||
var enableDisableMolecules: [FormValidationEnableDisableProtocol] = []
|
||||
var radioButtonsModelByGroup: [String: RadioButtonModel] = [:]
|
||||
|
||||
public func insertMolecule(_ molecule: UIView & FormValidationProtocol) {
|
||||
molecules.append(molecule)
|
||||
public func insertMolecule(_ molecule: FormValidationProtocol) {
|
||||
if let molecule = molecule as? FormValidationFormFieldProtocol {
|
||||
fieldMolecules.append(molecule)
|
||||
}
|
||||
if let moleculeT = molecule as? FormValidationEnableDisableProtocol,
|
||||
moleculeT.isValidationRequired() {
|
||||
enableDisableMolecules.append(moleculeT)
|
||||
}
|
||||
}
|
||||
|
||||
public static func getFormValidatorFor(delegate: FormValidationProtocol) -> FormValidator? {
|
||||
if let delegateFormValidatorModel = delegate.formValidatorModel,
|
||||
let validator = delegateFormValidatorModel() {
|
||||
return validator
|
||||
} else {
|
||||
return nil
|
||||
public static func enableByValidationWith(delegate: FormValidationProtocol?) {
|
||||
if let delegate = delegate {
|
||||
let formValidator = FormValidator.getFormValidatorFor(delegate: delegate)
|
||||
formValidator?.enableByValidation()
|
||||
}
|
||||
}
|
||||
|
||||
public static func setupValidation(molecule: UIView & FormValidationProtocol, delegate: FormValidationProtocol?) {
|
||||
if let delegateFormValidatorModel = delegate?.formValidatorModel,
|
||||
let validator = delegateFormValidatorModel() {
|
||||
|
||||
public static func getFormValidatorFor(delegate: FormValidationProtocol) -> FormValidator? {
|
||||
return delegate.formValidatorModel?()
|
||||
}
|
||||
|
||||
public static func setupValidation(molecule: FormValidationProtocol, delegate: FormValidationProtocol?) {
|
||||
if let validator = delegate?.formValidatorModel?() {
|
||||
validator.delegate = delegate
|
||||
validator.insertMolecule(molecule)
|
||||
}
|
||||
}
|
||||
|
||||
public func enableByValidation() {
|
||||
for molecule in enableDisableMolecules {
|
||||
var requiredGroups = molecule.requiredGroups?() ?? [dummyGroupName]
|
||||
if requiredGroups.count == 0 {
|
||||
requiredGroups = [dummyGroupName]
|
||||
}
|
||||
enableWithGroups(requiredGroups, molecule)
|
||||
}
|
||||
}
|
||||
|
||||
public func enableWithGroups(_ requiredGroupList: [String], _ enableDisableMolecule: FormValidationEnableDisableProtocol) {
|
||||
let requiredGroupSet = Set(requiredGroupList)
|
||||
var valid = true
|
||||
for molecule in molecules {
|
||||
if let isValidField = molecule.isValidField,
|
||||
isValidField() == false {
|
||||
valid = false
|
||||
for molecule in fieldMolecules {
|
||||
let groupName = molecule.formFieldGroupName() ?? dummyGroupName
|
||||
if requiredGroupSet.contains(groupName) {
|
||||
valid = valid && molecule.isValidField()
|
||||
if valid == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
enableDisableMolecule.enableField?(valid)
|
||||
}
|
||||
|
||||
public func enableIgnoreGroupName(_ enableDisableMolecules: FormValidationEnableDisableProtocol) {
|
||||
var valid = true
|
||||
for molecule in fieldMolecules {
|
||||
valid = valid && molecule.isValidField()
|
||||
if (!valid) {
|
||||
break
|
||||
}
|
||||
}
|
||||
let enableField = valid && (extraValidationBlock?() ?? true)
|
||||
shouldEnable(enableField)
|
||||
}
|
||||
|
||||
public func shouldEnable(_ enable: Bool) {
|
||||
for molecule in molecules {
|
||||
if let enableField = molecule.enableField {
|
||||
enableField(enable)
|
||||
}
|
||||
}
|
||||
enableDisableMolecules.enableField?(enableField)
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,7 +330,7 @@
|
||||
bottomViewBot.active = YES;
|
||||
|
||||
UIView *safeAreaView = [MVMCoreUICommonViewsUtility getAndSetupSafeAreaViewOnView:self.view];
|
||||
safeAreaView.backgroundColor = footerView.backgroundColor;
|
||||
safeAreaView.backgroundColor = self.bottomView.backgroundColor;
|
||||
self.safeAreaView = safeAreaView;
|
||||
|
||||
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[footerView]-0@900-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(footerView)]];
|
||||
|
||||
@ -91,7 +91,7 @@ import UIKit
|
||||
imageLoader.updateView(size)
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 197
|
||||
}
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ import UIKit
|
||||
imageView.reset()
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 95
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeVi
|
||||
backgroundColor = .white
|
||||
}
|
||||
|
||||
public static func name(forReuse molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
public class func name(forReuse molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
guard let molecule = molecule?.optionalDictionaryForKey(KeyMolecule) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
//
|
||||
// MoleculeTableViewCell.swift
|
||||
// TableViewCell.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/18/19.
|
||||
// Created by Scott Pfeil on 10/29/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class MoleculeTableViewCell: UITableViewCell, MVMCoreUIMoleculeViewProtocol, MoleculeListCellProtocol {
|
||||
|
||||
@objcMembers open class TableViewCell: UITableViewCell, MVMCoreUIMoleculeViewProtocol, MoleculeListCellProtocol {
|
||||
open var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)?
|
||||
open var json: [AnyHashable: Any]?
|
||||
|
||||
@ -17,7 +16,7 @@ import UIKit
|
||||
open var updateViewHorizontalDefaults = true
|
||||
|
||||
// For the accessory view convenience.
|
||||
public var caretView: CaretView?
|
||||
private var caretView: CaretView?
|
||||
private var caretViewWidthSizeObject: MFSizeObject?
|
||||
private var caretViewHeightSizeObject: MFSizeObject?
|
||||
|
||||
@ -25,20 +24,22 @@ import UIKit
|
||||
public var topSeparatorView: SeparatorView?
|
||||
public var bottomSeparatorView: SeparatorView?
|
||||
public enum SeparatorFrequency: String {
|
||||
case All = "all"
|
||||
case AllExceptTop = "allExceptTop"
|
||||
case AllExceptBottom = "allExceptBottom"
|
||||
case Between = "between"
|
||||
case all
|
||||
case allExceptTop
|
||||
case allExceptBottom
|
||||
case between
|
||||
}
|
||||
|
||||
/// For subclasses that want to use a custom accessory view.
|
||||
open var customAccessoryView = false
|
||||
|
||||
public var topMarginPadding: CGFloat = 24
|
||||
public var bottomMarginPadding: CGFloat = 24
|
||||
open var topMarginPadding: CGFloat = 24
|
||||
open var bottomMarginPadding: CGFloat = 24
|
||||
|
||||
private var heroAccessoryCenter: CGPoint?
|
||||
|
||||
// MARK: - Styling
|
||||
func style(with styleString: String?) {
|
||||
open func style(with styleString: String?) {
|
||||
guard let styleString = styleString else {
|
||||
return
|
||||
}
|
||||
@ -53,6 +54,40 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
open func styleStandard() {
|
||||
topMarginPadding = 24
|
||||
bottomMarginPadding = 24
|
||||
bottomSeparatorView?.show()
|
||||
bottomSeparatorView?.setAsLight()
|
||||
}
|
||||
|
||||
open func styleHeader() {
|
||||
topMarginPadding = 48
|
||||
bottomMarginPadding = 16
|
||||
bottomSeparatorView?.show()
|
||||
bottomSeparatorView?.setAsRegular()
|
||||
}
|
||||
|
||||
open func styleNone() {
|
||||
topMarginPadding = 0
|
||||
bottomMarginPadding = 0
|
||||
bottomSeparatorView?.hide()
|
||||
}
|
||||
|
||||
/// Adds the molecule to the view.
|
||||
open func addMolecule(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {
|
||||
contentView.addSubview(molecule)
|
||||
let standardConstraints = (molecule as? MVMCoreUIViewConstrainingProtocol)?.useStandardConstraints?() ?? true
|
||||
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: molecule, useMargins: standardConstraints).values))
|
||||
|
||||
// This molecule will by default handle margins.
|
||||
if let castView = molecule as? MVMCoreUIViewConstrainingProtocol {
|
||||
castView.shouldSetHorizontalMargins?(false)
|
||||
castView.shouldSetVerticalMargins?(false)
|
||||
}
|
||||
self.molecule = molecule
|
||||
}
|
||||
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
@ -62,33 +97,6 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
var heroAccessoryCenter: CGPoint?
|
||||
|
||||
func styleStandard() {
|
||||
topMarginPadding = 24
|
||||
bottomMarginPadding = 24
|
||||
bottomSeparatorView?.show()
|
||||
bottomSeparatorView?.setAsLight()
|
||||
}
|
||||
|
||||
func styleHeader() {
|
||||
topMarginPadding = 48
|
||||
bottomMarginPadding = 16
|
||||
bottomSeparatorView?.show()
|
||||
bottomSeparatorView?.setAsRegular()
|
||||
}
|
||||
|
||||
func styleNone() {
|
||||
topMarginPadding = 0
|
||||
bottomMarginPadding = 0
|
||||
bottomSeparatorView?.hide()
|
||||
}
|
||||
|
||||
public func willDisplay() {
|
||||
|
||||
alignAccessoryToHero()
|
||||
}
|
||||
|
||||
// MARK: - Inits
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
@ -129,6 +137,83 @@ import UIKit
|
||||
contentView.preservesSuperviewLayoutMargins = false
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||
public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
self.json = json
|
||||
|
||||
guard let json = json else { return }
|
||||
|
||||
style(with: json.optionalStringForKey("style"))
|
||||
|
||||
if let useHorizontalMargins = json.optionalBoolForKey("useHorizontalMargins") {
|
||||
updateViewHorizontalDefaults = useHorizontalMargins
|
||||
}
|
||||
|
||||
if (json.optionalBoolForKey("useVerticalMargins") ?? true) == false {
|
||||
topMarginPadding = 0
|
||||
bottomMarginPadding = 0
|
||||
}
|
||||
|
||||
if let backgroundColorString = json.optionalStringForKey(KeyBackgroundColor) {
|
||||
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
|
||||
}
|
||||
|
||||
// Add the caret if there is an action and it's not declared hidden.
|
||||
if !customAccessoryView {
|
||||
if let _ = json.optionalDictionaryForKey("actionMap"), !json.boolForKey("hideArrow") {
|
||||
addCaretViewAccessory()
|
||||
} else {
|
||||
accessoryView = nil
|
||||
}
|
||||
}
|
||||
|
||||
// override the separator
|
||||
if let separator = json.optionalDictionaryForKey("separator") {
|
||||
addSeparatorsIfNeeded()
|
||||
bottomSeparatorView?.setWithJSON(separator, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
guard let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule) else { return }
|
||||
molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
|
||||
|
||||
// This molecule will by default handle margins.
|
||||
if let castView = molecule as? MVMCoreUIViewConstrainingProtocol {
|
||||
castView.shouldSetHorizontalMargins?(false)
|
||||
castView.shouldSetVerticalMargins?(false)
|
||||
}
|
||||
}
|
||||
|
||||
public func reset() {
|
||||
molecule?.reset?()
|
||||
updateViewHorizontalDefaults = true
|
||||
styleStandard()
|
||||
backgroundColor = .white
|
||||
}
|
||||
|
||||
public class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) else {
|
||||
return 80
|
||||
}
|
||||
return max(2 * PaddingDefaultVerticalSpacing3, height)
|
||||
}
|
||||
|
||||
public class func name(forReuse molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
return molecule?.optionalStringForKey(KeyMoleculeName) ?? ""
|
||||
}
|
||||
|
||||
// MARK: - Arrow
|
||||
/// Adds the standard mvm style caret to the accessory view
|
||||
@objc public func addCaretViewAccessory() {
|
||||
guard accessoryView == nil else { return }
|
||||
let width: CGFloat = 6
|
||||
let height: CGFloat = 10
|
||||
caretView = CaretView(lineThickness: CaretView.thin)
|
||||
caretView?.frame = CGRect(x: 0, y: 0, width: width, height: height)
|
||||
caretViewWidthSizeObject = MFSizeObject(standardSize: width, standardiPadPortraitSize: 9)
|
||||
caretViewHeightSizeObject = MFSizeObject(standardSize: height, standardiPadPortraitSize: 16)
|
||||
accessoryView = caretView
|
||||
}
|
||||
|
||||
/// NOTE: Should only be called when displayed or about to be displayed.
|
||||
public func alignAccessoryToHero() {
|
||||
|
||||
@ -160,103 +245,6 @@ import UIKit
|
||||
return findHeroLabel(views: queue)
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||
public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
self.json = json
|
||||
|
||||
style(with: json?.optionalStringForKey("style"))
|
||||
|
||||
if let useHorizontalMargins = json?.optionalBoolForKey("useHorizontalMargins") {
|
||||
updateViewHorizontalDefaults = useHorizontalMargins
|
||||
}
|
||||
|
||||
if (json?.optionalBoolForKey("useVerticalMargins") ?? true) == false {
|
||||
topMarginPadding = 0
|
||||
bottomMarginPadding = 0
|
||||
}
|
||||
|
||||
if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) {
|
||||
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
|
||||
}
|
||||
|
||||
// Add the caret if there is an action and it's not declared hidden.
|
||||
if !customAccessoryView {
|
||||
if let _ = json?.optionalDictionaryForKey("actionMap"), !json!.boolForKey("hideArrow") {
|
||||
addCaretViewAccessory()
|
||||
} else {
|
||||
accessoryView = nil
|
||||
}
|
||||
}
|
||||
|
||||
// override the separator
|
||||
if let separator = json?.optionalDictionaryForKey("separator") {
|
||||
addSeparatorsIfNeeded()
|
||||
bottomSeparatorView?.setWithJSON(separator, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
guard let json = json, let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule) else { return }
|
||||
|
||||
if molecule == nil {
|
||||
if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) {
|
||||
contentView.addSubview(moleculeView)
|
||||
let standardConstraints = (moleculeView as? MVMCoreUIViewConstrainingProtocol)?.useStandardConstraints?() ?? true
|
||||
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: standardConstraints).values))
|
||||
molecule = moleculeView
|
||||
}
|
||||
} else {
|
||||
molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
// This molecule will by default handle margins.
|
||||
if let castView = molecule as? MVMCoreUIViewConstrainingProtocol {
|
||||
castView.shouldSetHorizontalMargins?(false)
|
||||
castView.shouldSetVerticalMargins?(false)
|
||||
}
|
||||
}
|
||||
|
||||
public func reset() {
|
||||
molecule?.reset?()
|
||||
updateViewHorizontalDefaults = true
|
||||
styleStandard()
|
||||
backgroundColor = .white
|
||||
}
|
||||
|
||||
public static func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) else {
|
||||
return 80
|
||||
}
|
||||
return max(2 * PaddingDefaultVerticalSpacing3, height)
|
||||
}
|
||||
|
||||
public static func name(forReuse molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
guard let molecule = molecule?.optionalDictionaryForKey(KeyMolecule) else {
|
||||
return "\(self)<>"
|
||||
}
|
||||
let moleculeName = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) ?? ""
|
||||
return "\(self)<\(moleculeName)>"
|
||||
}
|
||||
|
||||
public static func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||
guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule),
|
||||
let theClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON) else {
|
||||
return nil
|
||||
}
|
||||
return theClass.requiredModules?(moleculeJSON, delegateObject: delegateObject, error: error)
|
||||
}
|
||||
|
||||
// MARK: - Arrow
|
||||
/// Adds the standard mvm style caret to the accessory view
|
||||
@objc public func addCaretViewAccessory() {
|
||||
guard accessoryView == nil else { return }
|
||||
let width: CGFloat = 6
|
||||
let height: CGFloat = 10
|
||||
caretView = CaretView(lineThickness: CaretView.thin)
|
||||
caretView?.frame = CGRect(x: 0, y: 0, width: width, height: height)
|
||||
caretViewWidthSizeObject = MFSizeObject(standardSize: width, standardiPadPortraitSize: 9)
|
||||
caretViewHeightSizeObject = MFSizeObject(standardSize: height, standardiPadPortraitSize: 16)
|
||||
accessoryView = caretView
|
||||
}
|
||||
|
||||
// MARK: - MoleculeListCellProtocol
|
||||
/// For when the separator between cells shows using json and frequency. Default is type: standard, frequency: allExceptTop.
|
||||
public func setSeparatorWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, indexPath: IndexPath) {
|
||||
@ -270,7 +258,7 @@ import UIKit
|
||||
} else {
|
||||
topSeparatorView?.hide()
|
||||
bottomSeparatorView?.setAsLight()
|
||||
setSeparatorFrequency(MoleculeTableViewCell.SeparatorFrequency.AllExceptTop, indexPath: indexPath)
|
||||
setSeparatorFrequency(TableViewCell.SeparatorFrequency.allExceptTop, indexPath: indexPath)
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,8 +268,12 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
public func willDisplay() {
|
||||
alignAccessoryToHero()
|
||||
}
|
||||
|
||||
// MARK: - Separator
|
||||
func addSeparatorsIfNeeded() {
|
||||
open func addSeparatorsIfNeeded() {
|
||||
if topSeparatorView == nil {
|
||||
topSeparatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionTop)
|
||||
topSeparatorView?.hide()
|
||||
@ -295,24 +287,24 @@ import UIKit
|
||||
/// For when the separator between cells shows.
|
||||
public func setSeparatorFrequency(_ separatorFrequency: SeparatorFrequency, indexPath: IndexPath) {
|
||||
switch separatorFrequency {
|
||||
case .All:
|
||||
case .all:
|
||||
if indexPath.row == 0 {
|
||||
topSeparatorView?.show()
|
||||
} else {
|
||||
topSeparatorView?.hide()
|
||||
}
|
||||
bottomSeparatorView?.show()
|
||||
case .AllExceptBottom:
|
||||
case .allExceptBottom:
|
||||
topSeparatorView?.show()
|
||||
bottomSeparatorView?.hide()
|
||||
case .Between:
|
||||
case .between:
|
||||
if indexPath.row == 0 {
|
||||
topSeparatorView?.hide()
|
||||
} else {
|
||||
topSeparatorView?.show()
|
||||
}
|
||||
bottomSeparatorView?.hide()
|
||||
case .AllExceptTop:
|
||||
case .allExceptTop:
|
||||
fallthrough
|
||||
default:
|
||||
topSeparatorView?.hide()
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers public class TabsTableViewCell: MoleculeTableViewCell {
|
||||
@objcMembers public class TabsTableViewCell: TableViewCell {
|
||||
let tabs = TopTabbar(frame: .zero)
|
||||
var delegateObject: MVMCoreUIDelegateObject?
|
||||
var previousTabIndex = 0
|
||||
|
||||
@ -174,7 +174,7 @@ import UIKit
|
||||
bottomRightLabel.styleB3(true)
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 34
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,9 +8,9 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers public class HeadlineBodySwitch: ViewConstrainingView {
|
||||
let headlineBody = HeadlineBody(frame: .zero)
|
||||
let mvmSwitch = MVMCoreUISwitch.mvmSwitchDefault()
|
||||
@objcMembers open class HeadlineBodySwitch: ViewConstrainingView {
|
||||
public let headlineBody = HeadlineBody(frame: .zero)
|
||||
public let mvmSwitch = MVMCoreUISwitch.mvmSwitchDefault()
|
||||
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
@ -19,7 +19,7 @@ import UIKit
|
||||
mvmSwitch.updateView(size)
|
||||
}
|
||||
|
||||
public override func setupView() {
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
guard mvmSwitch.superview == nil else {
|
||||
return
|
||||
@ -35,24 +35,24 @@ import UIKit
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||
public 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)
|
||||
headlineBody.setWithJSON(json?.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData)
|
||||
mvmSwitch.setWithJSON(json?.optionalDictionaryForKey("switch"), delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
open override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 30
|
||||
}
|
||||
|
||||
public override func setAsMolecule() {
|
||||
open override func setAsMolecule() {
|
||||
super.setAsMolecule()
|
||||
headlineBody.setAsMolecule()
|
||||
(mvmSwitch as MVMCoreUIMoleculeViewProtocol).setAsMolecule?()
|
||||
headlineBody.styleListItem()
|
||||
}
|
||||
|
||||
public override func reset() {
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
headlineBody.reset()
|
||||
(mvmSwitch as MVMCoreUIMoleculeViewProtocol).reset?()
|
||||
|
||||
@ -41,7 +41,7 @@ import UIKit
|
||||
mvmSwitch.setWithJSON(json?.optionalDictionaryForKey("switch"), delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return HeadlineBodyTextButton.estimatedHeight(forRow: json, delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ import UIKit
|
||||
mvmSwitch.setWithJSON(json?.optionalDictionaryForKey("switch"), delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return MVMCoreUISwitch.estimatedHeight(forRow: json, delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
|
||||
@ -54,7 +54,7 @@ open class ModuleMolecule: ViewConstrainingView {
|
||||
moduleMolecule?.reset?()
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
guard let moduleName = json?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else {
|
||||
// Critical error
|
||||
return 0
|
||||
@ -62,7 +62,7 @@ open class ModuleMolecule: ViewConstrainingView {
|
||||
return MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: module)?.estimatedHeight?(forRow: module, delegateObject: delegateObject) ?? 0
|
||||
}
|
||||
|
||||
public override static func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
public override class func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
guard let moduleName = molecule?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else {
|
||||
// Critical error
|
||||
return "moduleMolecule<>"
|
||||
@ -70,7 +70,7 @@ open class ModuleMolecule: ViewConstrainingView {
|
||||
return "moduleMolecule<" + (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: module)?.name?(forReuse: module, delegateObject: delegateObject) ?? module.stringForkey(KeyMoleculeName)) + ">"
|
||||
}
|
||||
|
||||
public override static func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||
public override class func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||
let moduleName = json?.optionalStringForKey("moduleName")
|
||||
if moduleName == nil || delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) == nil {
|
||||
if let errorObject = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), code: CoreUIErrorCode.ErrorCodeModuleMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) {
|
||||
|
||||
90
MVMCoreUI/Molecules/RadioButtonLabel.swift
Normal file
90
MVMCoreUI/Molecules/RadioButtonLabel.swift
Normal file
@ -0,0 +1,90 @@
|
||||
//
|
||||
// RadioButtonWithLabel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 10/21/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers public class RadioButtonLabel: ViewConstrainingView {
|
||||
|
||||
public let radioButton = RadioButton()
|
||||
var delegateObject: MVMCoreUIDelegateObject?
|
||||
let label = Label()
|
||||
|
||||
// MARK: - Inits
|
||||
public init() {
|
||||
super.init(frame: .zero)
|
||||
}
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
}
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
|
||||
public override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
radioButton.updateView(size)
|
||||
label.updateView(size)
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
guard subviews.count == 0 else {
|
||||
return
|
||||
}
|
||||
|
||||
addSubview(radioButton)
|
||||
radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true
|
||||
radioButton.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne).isActive = true
|
||||
layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true
|
||||
radioButton.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor).isActive = true
|
||||
|
||||
if let rightView = createRightView() {
|
||||
addSubview(rightView)
|
||||
rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true
|
||||
rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true
|
||||
|
||||
var constraint = rightView.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne)
|
||||
constraint.priority = .defaultHigh
|
||||
constraint.isActive = true
|
||||
|
||||
constraint = layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: rightView.bottomAnchor, constant: PaddingOne)
|
||||
constraint.priority = .defaultHigh
|
||||
constraint.isActive = true
|
||||
layoutMarginsGuide.centerYAnchor.constraint(equalTo: rightView.centerYAnchor).isActive = true
|
||||
}
|
||||
}
|
||||
|
||||
func createRightView() -> ViewConstrainingView? {
|
||||
let rightView = ViewConstrainingView(constrainingView: label)
|
||||
return rightView
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||
extension RadioButtonLabel {
|
||||
@objc open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||
self.delegateObject = delegateObject
|
||||
radioButton.setWithJSON(json?.optionalDictionaryForKey("radioButton"), delegateObject: delegateObject, additionalData: additionalData)
|
||||
label.setWithJSON(json?.optionalDictionaryForKey(KeyLabel),
|
||||
delegateObject: delegateObject,
|
||||
additionalData: additionalData)
|
||||
}
|
||||
|
||||
public override func reset() {
|
||||
super.reset()
|
||||
radioButton.reset()
|
||||
label.reset()
|
||||
}
|
||||
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 45
|
||||
}
|
||||
}
|
||||
54
MVMCoreUI/Molecules/RadioButtonModel.swift
Normal file
54
MVMCoreUI/Molecules/RadioButtonModel.swift
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// RadioButtonModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 5/14/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
@objcMembers public class RadioButtonModel: NSObject {
|
||||
|
||||
private var selectedRadioButton: RadioButton?
|
||||
private var fieldGroupName: String?
|
||||
|
||||
public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonModel {
|
||||
guard let groupName = radioButton.radioGroupName,
|
||||
let formValidator = formValidator else {
|
||||
return RadioButtonModel()
|
||||
}
|
||||
|
||||
let radioButtonModel = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonModel()
|
||||
radioButtonModel.fieldGroupName = radioButton.formFieldGroupName()
|
||||
formValidator.radioButtonsModelByGroup[groupName] = radioButtonModel
|
||||
return radioButtonModel
|
||||
}
|
||||
|
||||
public func selected(_ radioButton: RadioButton) {
|
||||
selectedRadioButton?.isSelected = false
|
||||
selectedRadioButton = radioButton
|
||||
selectedRadioButton?.isSelected = true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - FormValidationFormFieldProtocol
|
||||
extension RadioButtonModel: FormValidationFormFieldProtocol {
|
||||
public func formFieldGroupName() -> String? {
|
||||
return selectedRadioButton?.formFieldGroupName() ?? self.fieldGroupName
|
||||
}
|
||||
|
||||
// Used to check the validity of the field, to enable/disable the primary button.
|
||||
@objc public func isValidField() -> Bool {
|
||||
return selectedRadioButton != nil ? true : false
|
||||
}
|
||||
// Name of the field to send to server
|
||||
@objc public func formFieldName() -> String? {
|
||||
return selectedRadioButton?.fieldKey
|
||||
}
|
||||
// The field value key value pair for sending to server
|
||||
@objc public func formFieldValue() -> Any? {
|
||||
return selectedRadioButton != nil ? true : false
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,7 @@ open class StandardFooterView: ViewConstrainingView {
|
||||
(molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(false)
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
if let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) {
|
||||
return height + PaddingDefaultVerticalSpacing + PaddingDefaultVerticalSpacing
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ public class StandardHeaderView: ViewConstrainingView {
|
||||
separatorView?.show()
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
if let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) {
|
||||
return height + PaddingDefaultVerticalSpacing + PaddingDefaultVerticalSpacing
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ import UIKit
|
||||
body.styleB2(true)
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 65
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ open class HeadlineBody: ViewConstrainingView {
|
||||
stylePageHeader()
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 58
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ import UIKit
|
||||
textButton.reset()
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 60
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ public class MoleculeStackView: ViewConstrainingView {
|
||||
}
|
||||
}
|
||||
|
||||
public override static func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
public override class func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
// This will aggregate names of molecules to make an id.
|
||||
guard let molecules = molecule?.optionalArrayForKey(KeyMolecules) else {
|
||||
return "stack<>"
|
||||
@ -199,7 +199,7 @@ public class MoleculeStackView: ViewConstrainingView {
|
||||
return name
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
guard let items = json?.optionalArrayForKey(KeyMolecules) else {
|
||||
return 0
|
||||
}
|
||||
@ -221,7 +221,7 @@ public class MoleculeStackView: ViewConstrainingView {
|
||||
return estimatedHeight
|
||||
}
|
||||
|
||||
public override static func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||
public override class func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||
guard let items = json?.optionalArrayForKey(KeyMolecules) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
dispatch_once(&onceToken, ^{
|
||||
mapping = [@{
|
||||
@"label": Label.class,
|
||||
@"separator": SeparatorView.class,
|
||||
@"line": SeparatorView.class,
|
||||
@"button": ButtonView.class,
|
||||
@"textButton": MFTextButton.class,
|
||||
@"header": StandardHeaderView.class,
|
||||
@ -40,8 +40,11 @@
|
||||
@"checkbox" : Checkbox.class,
|
||||
@"checkboxWithLabelView" : CheckboxWithLabelView.class,
|
||||
@"cornerLabels" : CornerLabels.class,
|
||||
@"progressBar": ProgressBar.class,
|
||||
@"progressbar": ProgressBar.class,
|
||||
@"multiProgressBar": MultiProgress.class,
|
||||
@"checkbox": MVMCoreUICheckBox.class,
|
||||
@"radioButton": RadioButton.class,
|
||||
@"radioButtonLabel": RadioButtonLabel.class,
|
||||
@"listItem": MoleculeTableViewCell.class,
|
||||
@"accordionListItem": AccordionMoleculeTableViewCell.class,
|
||||
@"switch": MVMCoreUISwitch.class,
|
||||
|
||||
@ -36,6 +36,7 @@ extern CGFloat const PaddingHorizontalLarge;
|
||||
extern CGFloat const PaddingVerticalWhiteGrayView;
|
||||
extern CGFloat const PaddingVerticalHeadlineAlternate;
|
||||
extern CGFloat const PaddingPrimaryButtonTop;
|
||||
extern CGFloat const PaddingHorizontalBetweenRelatedItems;
|
||||
|
||||
// These are based on the multiple of 6 rule
|
||||
extern CGFloat const PaddingOne;
|
||||
|
||||
@ -26,6 +26,7 @@ CGFloat const PaddingVerticalWhiteGrayView = 72;
|
||||
CGFloat const PaddingVerticalHeadlineAlternate = 48;
|
||||
CGFloat const PaddingPrimaryButtonTop = 36;
|
||||
|
||||
CGFloat const PaddingHorizontalBetweenRelatedItems = 16;
|
||||
CGFloat const PaddingOne = 6;
|
||||
CGFloat const PaddingTwo = 12;
|
||||
CGFloat const PaddingThree = 18;
|
||||
|
||||
@ -36,6 +36,13 @@
|
||||
"checkbox_checked_state" = "Checked";
|
||||
"checkbox_unchecked_state" = "Unchecked";
|
||||
"checkbox_desc_state" = "%@ CheckBox %@";
|
||||
|
||||
// Radio Button
|
||||
"radio_action_hint" = "Double tap to select";
|
||||
"radio_selected_state" = "Selected";
|
||||
"radio_not_selected_state" = "Not Selected";
|
||||
"radio_desc_state" = "Option";
|
||||
|
||||
// Switch
|
||||
"mfswitch_buttonlabel" = "Switch Button";
|
||||
"AccOn" = "on";
|
||||
|
||||
@ -37,6 +37,11 @@
|
||||
"checkbox_checked_state" = "Verificado";
|
||||
"checkbox_unchecked_state" = "Sin marcar";
|
||||
"checkbox_desc_state" = "%@ Casilla %@";
|
||||
// Radio Button
|
||||
"radio_action_hint" = "Toca dos veces para seleccionar.";
|
||||
"radio_selected_state" = "Seleccionado";
|
||||
"radio_not_selected_state" = "No Seleccionado";
|
||||
"radio_desc_state" = "Opción";
|
||||
// Switch
|
||||
"mfswitch_buttonlabel" = "Botón Cambiar";
|
||||
"AccOn" = "encendido";
|
||||
|
||||
@ -37,6 +37,13 @@
|
||||
"checkbox_checked_state" = "Verificado";
|
||||
"checkbox_unchecked_state" = "Sin marcar";
|
||||
"checkbox_desc_state" = "%@ Casilla %@";
|
||||
|
||||
// Radio Button
|
||||
"radio_action_hint" = "Toca dos veces para seleccionar.";
|
||||
"radio_selected_state" = "Seleccionado";
|
||||
"radio_not_selected_state" = "No Seleccionado";
|
||||
"radio_desc_state" = "Opción";
|
||||
|
||||
// Switch
|
||||
"mfswitch_buttonlabel" = "Botón Cambiar";
|
||||
"AccOn" = "encendido";
|
||||
|
||||
@ -126,7 +126,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController {
|
||||
open override func addMolecules(_ molecules: [[AnyHashable : Any]], 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.
|
||||
DispatchQueue.main.async {
|
||||
guard let cell = sender as? MoleculeTableViewCell, let indexPath = self.tableView?.indexPath(for: cell) else { return }
|
||||
guard let indexPath = self.tableView?.indexPath(for: sender) else { return }
|
||||
var indexPaths: [IndexPath] = []
|
||||
for molecule in molecules {
|
||||
if let info = self.getMoleculeInfo(with: molecule) {
|
||||
|
||||
@ -33,6 +33,7 @@ static const CGFloat VertialShadowOffset = 6;
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
view.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
view.backgroundColor = [UIColor clearColor];
|
||||
view.directionalLayoutMargins = NSDirectionalEdgeInsetsZero;
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user