merge from develop

This commit is contained in:
Kevin G Christiano 2020-02-07 09:20:39 -05:00
commit d02586f613
35 changed files with 1187 additions and 386 deletions

View File

@ -111,6 +111,10 @@
9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; };
946EE1BA237B66D80036751F /* MoleculeModelHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946EE1B9237B66D80036751F /* MoleculeModelHelper.swift */; }; 946EE1BA237B66D80036751F /* MoleculeModelHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946EE1B9237B66D80036751F /* MoleculeModelHelper.swift */; };
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; };
94AF4A3E23E9D13900676048 /* MFCaretButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AF4A3C23E9D13900676048 /* MFCaretButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94AF4A3D23E9D13900676048 /* MFCaretButton.m */; };
94AF4A4223E9D19E00676048 /* MFCaretView.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AF4A4023E9D19E00676048 /* MFCaretView.h */; settings = {ATTRIBUTES = (Public, ); }; };
94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94AF4A4123E9D19E00676048 /* MFCaretView.m */; };
94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */; }; 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */; };
94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */; }; 94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */; };
94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A223872C110006CF46 /* LabelAttributeStrikeThroughModel.swift */; }; 94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A223872C110006CF46 /* LabelAttributeStrikeThroughModel.swift */; };
@ -120,6 +124,8 @@
94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */; }; 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */; };
94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */; }; 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */; };
94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */; }; 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */; };
94F217B623E0BF6100A47C06 /* PrimaryButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = 94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; };
94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; };
94FB966223D797DA003D482B /* MFTextButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94FB966023D797DA003D482B /* MFTextButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94FB966223D797DA003D482B /* MFTextButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94FB966023D797DA003D482B /* MFTextButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
94FB966323D797DA003D482B /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94FB966123D797DA003D482B /* MFTextButton.m */; }; 94FB966323D797DA003D482B /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94FB966123D797DA003D482B /* MFTextButton.m */; };
C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; }; C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; };
@ -318,12 +324,15 @@
D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99923D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift */; }; D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99923D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift */; };
D2E2A99C23D8D975000B42E6 /* ImageHeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99B23D8D975000B42E6 /* ImageHeadlineBodyModel.swift */; }; D2E2A99C23D8D975000B42E6 /* ImageHeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99B23D8D975000B42E6 /* ImageHeadlineBodyModel.swift */; };
D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */; }; D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */; };
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99E23E07F8A000B42E6 /* PillButton.swift */; };
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */; };
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */; };
D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */; }; D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */; };
D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */; }; D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */; };
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; }; DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; };
DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; }; DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; };
DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; }; DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; };
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391A224421A0001AB423 /* CaretButton.swift */; }; DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391A224421A0001AB423 /* CaretLink.swift */; };
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */; }; DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */; };
DBEFFA04225A829700230692 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB891E822253FA8500022516 /* Label.swift */; }; DBEFFA04225A829700230692 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB891E822253FA8500022516 /* Label.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -425,6 +434,10 @@
9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = "<group>"; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = "<group>"; };
946EE1B9237B66D80036751F /* MoleculeModelHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeModelHelper.swift; sourceTree = "<group>"; }; 946EE1B9237B66D80036751F /* MoleculeModelHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeModelHelper.swift; sourceTree = "<group>"; };
948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = "<group>"; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = "<group>"; };
94AF4A3C23E9D13900676048 /* MFCaretButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFCaretButton.h; sourceTree = "<group>"; };
94AF4A3D23E9D13900676048 /* MFCaretButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFCaretButton.m; sourceTree = "<group>"; };
94AF4A4023E9D19E00676048 /* MFCaretView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFCaretView.h; sourceTree = "<group>"; };
94AF4A4123E9D19E00676048 /* MFCaretView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFCaretView.m; sourceTree = "<group>"; };
94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeModel.swift; sourceTree = "<group>"; }; 94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeModel.swift; sourceTree = "<group>"; };
94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeUnderlineModel.swift; sourceTree = "<group>"; }; 94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeUnderlineModel.swift; sourceTree = "<group>"; };
94C2D9A223872C110006CF46 /* LabelAttributeStrikeThroughModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeStrikeThroughModel.swift; sourceTree = "<group>"; }; 94C2D9A223872C110006CF46 /* LabelAttributeStrikeThroughModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeStrikeThroughModel.swift; sourceTree = "<group>"; };
@ -432,6 +445,8 @@
94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeColorModel.swift; sourceTree = "<group>"; }; 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeColorModel.swift; sourceTree = "<group>"; };
94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeImageModel.swift; sourceTree = "<group>"; }; 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeImageModel.swift; sourceTree = "<group>"; };
94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeActionModel.swift; sourceTree = "<group>"; }; 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeActionModel.swift; sourceTree = "<group>"; };
94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrimaryButtonView.h; sourceTree = "<group>"; };
94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; sourceTree = "<group>"; };
94FB966023D797DA003D482B /* MFTextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextButton.h; sourceTree = "<group>"; }; 94FB966023D797DA003D482B /* MFTextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextButton.h; sourceTree = "<group>"; };
94FB966123D797DA003D482B /* MFTextButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextButton.m; sourceTree = "<group>"; }; 94FB966123D797DA003D482B /* MFTextButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextButton.m; sourceTree = "<group>"; };
C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; }; C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; };
@ -643,6 +658,9 @@
D2E2A99723D8D63C000B42E6 /* ActionDetailWithImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImageModel.swift; sourceTree = "<group>"; }; D2E2A99723D8D63C000B42E6 /* ActionDetailWithImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImageModel.swift; sourceTree = "<group>"; };
D2E2A99923D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButtonModel.swift; sourceTree = "<group>"; }; D2E2A99923D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButtonModel.swift; sourceTree = "<group>"; };
D2E2A99B23D8D975000B42E6 /* ImageHeadlineBodyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageHeadlineBodyModel.swift; sourceTree = "<group>"; }; D2E2A99B23D8D975000B42E6 /* ImageHeadlineBodyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageHeadlineBodyModel.swift; sourceTree = "<group>"; };
D2E2A99E23E07F8A000B42E6 /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; };
D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModelProtocol.swift; sourceTree = "<group>"; };
D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableableModelProtocol.swift; sourceTree = "<group>"; };
D2F4DDE52371A4CB00CD28BB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; }; D2F4DDE52371A4CB00CD28BB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainer.swift; sourceTree = "<group>"; }; D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainer.swift; sourceTree = "<group>"; };
D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackItem.swift; sourceTree = "<group>"; }; D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackItem.swift; sourceTree = "<group>"; };
@ -650,7 +668,7 @@
DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; }; DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = "<group>"; }; DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = "<group>"; };
DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = "<group>"; }; DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = "<group>"; };
DBC4391A224421A0001AB423 /* CaretButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretButton.swift; sourceTree = "<group>"; }; DBC4391A224421A0001AB423 /* CaretLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretLink.swift; sourceTree = "<group>"; };
DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelWithInternalButton.swift; sourceTree = "<group>"; }; DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelWithInternalButton.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -678,6 +696,7 @@
012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */, 012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */,
D28A837823C7D5BC00DFE4FC /* PageModelProtocol.swift */, D28A837823C7D5BC00DFE4FC /* PageModelProtocol.swift */,
011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */, 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */,
D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */,
); );
path = ModelProtocols; path = ModelProtocols;
sourceTree = "<group>"; sourceTree = "<group>";
@ -845,6 +864,13 @@
D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */, D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */,
D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */, D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */,
D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */, D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */,
94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */,
94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */,
D282AACA2243C61700C46919 /* ButtonView.swift */,
94AF4A3C23E9D13900676048 /* MFCaretButton.h */,
94AF4A3D23E9D13900676048 /* MFCaretButton.m */,
94AF4A4023E9D19E00676048 /* MFCaretView.h */,
94AF4A4123E9D19E00676048 /* MFCaretView.m */,
); );
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1171,13 +1197,13 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
01F2A03123A4498200D954D8 /* CaretLinkModel.swift */, 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */,
DBC4391A224421A0001AB423 /* CaretButton.swift */, DBC4391A224421A0001AB423 /* CaretLink.swift */,
D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */, D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */,
D282AACA2243C61700C46919 /* ButtonView.swift */, D2E2A99E23E07F8A000B42E6 /* PillButton.swift */,
D28A838823CCCFCB00DFE4FC /* LinkModel.swift */, D28A838823CCCFCB00DFE4FC /* LinkModel.swift */,
C07065C32395677300FBF997 /* Link.swift */,
D28A838C23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift */, D28A838C23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift */,
D28A837623C79FC600DFE4FC /* MFCustomButton+ActionModel.swift */, D28A837623C79FC600DFE4FC /* MFCustomButton+ActionModel.swift */,
C07065C32395677300FBF997 /* Link.swift */,
); );
path = Buttons; path = Buttons;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1376,6 +1402,7 @@
D2B18B7D236090D500A9AEDC /* BaseClasses */ = { D2B18B7D236090D500A9AEDC /* BaseClasses */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */,
C003506023AA94CD00B6AC29 /* Button.swift */, C003506023AA94CD00B6AC29 /* Button.swift */,
D2B18B7E2360913400A9AEDC /* Control.swift */, D2B18B7E2360913400A9AEDC /* Control.swift */,
D2B18B802360945C00A9AEDC /* View.swift */, D2B18B802360945C00A9AEDC /* View.swift */,
@ -1424,6 +1451,7 @@
D29DF27521E79E81003B2FB9 /* MVMCoreUILoggingHandler.h in Headers */, D29DF27521E79E81003B2FB9 /* MVMCoreUILoggingHandler.h in Headers */,
D29DF28B21E7AC2B003B2FB9 /* ViewConstrainingView.h in Headers */, D29DF28B21E7AC2B003B2FB9 /* ViewConstrainingView.h in Headers */,
D29DF2B321E7B76D003B2FB9 /* MFLoadingSpinner.h in Headers */, D29DF2B321E7B76D003B2FB9 /* MFLoadingSpinner.h in Headers */,
94AF4A3E23E9D13900676048 /* MFCaretButton.h in Headers */,
0A21DB8A235E06EF00C160A2 /* MFDigitTextBox.h in Headers */, 0A21DB8A235E06EF00C160A2 /* MFDigitTextBox.h in Headers */,
D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */, D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */,
0A21DB8C235E06EF00C160A2 /* MFDigitTextField.h in Headers */, 0A21DB8C235E06EF00C160A2 /* MFDigitTextField.h in Headers */,
@ -1442,6 +1470,7 @@
D29DF2CA21E7BFC8003B2FB9 /* MFSizeThreshold.h in Headers */, D29DF2CA21E7BFC8003B2FB9 /* MFSizeThreshold.h in Headers */,
D29DF28021E7AA51003B2FB9 /* MVMCoreUIDetailViewProtocol.h in Headers */, D29DF28021E7AA51003B2FB9 /* MVMCoreUIDetailViewProtocol.h in Headers */,
D29DF2BD21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h in Headers */, D29DF2BD21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h in Headers */,
94AF4A4223E9D19E00676048 /* MFCaretView.h in Headers */,
D29DF2EE21ECEADF003B2FB9 /* MFFonts.h in Headers */, D29DF2EE21ECEADF003B2FB9 /* MFFonts.h in Headers */,
D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */, D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */,
D29770F321F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h in Headers */, D29770F321F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h in Headers */,
@ -1454,6 +1483,7 @@
D29DF2A121E7AF4E003B2FB9 /* MVMCoreUIUtility.h in Headers */, D29DF2A121E7AF4E003B2FB9 /* MVMCoreUIUtility.h in Headers */,
D29DF17621E69E1F003B2FB9 /* PrimaryButton.h in Headers */, D29DF17621E69E1F003B2FB9 /* PrimaryButton.h in Headers */,
D29DF2C821E7BFC1003B2FB9 /* MFSizeObject.h in Headers */, D29DF2C821E7BFC1003B2FB9 /* MFSizeObject.h in Headers */,
94F217B623E0BF6100A47C06 /* PrimaryButtonView.h in Headers */,
D29DF32021ED0CBA003B2FB9 /* LabelView.h in Headers */, D29DF32021ED0CBA003B2FB9 /* LabelView.h in Headers */,
D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */, D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */,
D29DF2E121E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h in Headers */, D29DF2E121E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h in Headers */,
@ -1590,6 +1620,7 @@
D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */, D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */,
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */, 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */,
0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */, 0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */,
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */,
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */,
D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */,
@ -1605,6 +1636,7 @@
014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */,
D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */, D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */,
012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */, 012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */,
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */,
94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */,
D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */, D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */,
014AA73123C5059B006F3E93 /* ListPageTemplateModel.swift in Sources */, 014AA73123C5059B006F3E93 /* ListPageTemplateModel.swift in Sources */,
@ -1639,6 +1671,7 @@
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */, 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */,
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */, 0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */,
94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */,
0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */, 0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */,
0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */, 0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */,
D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */, D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */,
@ -1685,6 +1718,7 @@
944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */, 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */,
D2E2A99623D8CF85000B42E6 /* HeadlineBodyLinkToggleModel.swift in Sources */, D2E2A99623D8CF85000B42E6 /* HeadlineBodyLinkToggleModel.swift in Sources */,
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */, C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */,
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */, D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */,
@ -1735,10 +1769,12 @@
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */, D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */,
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */, 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */, 0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */,
94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */,
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */, 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */,
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */,
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */,
D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */,
94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */, 94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */,
D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */, D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */,
@ -1749,7 +1785,7 @@
D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */, D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */,
C003506123AA94CD00B6AC29 /* Button.swift in Sources */, C003506123AA94CD00B6AC29 /* Button.swift in Sources */,
0A14F6A523E4803A00EDF7F7 /* StackView.swift in Sources */, 0A14F6A523E4803A00EDF7F7 /* StackView.swift in Sources */,
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */, DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */,
0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */, 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */,
0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */, 0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */,
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */, 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */,

View File

@ -18,14 +18,21 @@ public enum ButtonSize: String, Codable {
case tiny case tiny
} }
public class ButtonModel: MoleculeModelProtocol { public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol {
public static var identifier: String = "button" public static var identifier: String = "button"
public var moleculeName: String? public var moleculeName: String?
public var backgroundColor: Color? public var backgroundColor: Color?
public var title: String public var title: String
public var action: ActionModelProtocol public var action: ActionModelProtocol
public var enabled: Bool = true
public var style: ButtonStyle? public var style: ButtonStyle?
public var size: ButtonSize? = .standard public var size: ButtonSize? = .standard
public var fillColor: Color?
public var textColor: Color?
public var borderColor: Color?
public var disabledFillColor: Color?
public var disabledTextColor: Color?
public var disabledBorderColor: Color?
public var required: Bool? public var required: Bool?
public var requiredGroups: [String]? public var requiredGroups: [String]?
@ -34,13 +41,26 @@ public class ButtonModel: MoleculeModelProtocol {
self.action = action self.action = action
} }
init(secondaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
style = .secondary
}
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case backgroundColor case backgroundColor
case title case title
case action case action
case enabled
case style case style
case size case size
case fillColor
case textColor
case borderColor
case disabledFillColor
case disabledTextColor
case disabledBorderColor
case required case required
case requiredGroups case requiredGroups
} }
@ -60,6 +80,15 @@ public class ButtonModel: MoleculeModelProtocol {
if let size = try typeContainer.decodeIfPresent(ButtonSize.self, forKey: .size) { if let size = try typeContainer.decodeIfPresent(ButtonSize.self, forKey: .size) {
self.size = size self.size = size
} }
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
fillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor)
textColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor)
borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor)
disabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledFillColor)
disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor)
disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -68,8 +97,16 @@ public class ButtonModel: MoleculeModelProtocol {
try container.encode(title, forKey: .title) try container.encode(title, forKey: .title)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeModel(action, forKey: .action) try container.encodeModel(action, forKey: .action)
try container.encode(enabled, forKey: .enabled)
try container.encodeIfPresent(style, forKey: .style) try container.encodeIfPresent(style, forKey: .style)
try container.encodeIfPresent(size, forKey: .size) try container.encodeIfPresent(size, forKey: .size)
try container.encodeIfPresent(fillColor, forKey: .fillColor)
try container.encodeIfPresent(textColor, forKey: .textColor)
try container.encodeIfPresent(borderColor, forKey: .borderColor)
try container.encodeIfPresent(disabledFillColor, forKey: .disabledFillColor)
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor)
try container.encodeIfPresent(disabledBorderColor, forKey: .disabledBorderColor)
try container.encodeIfPresent(required, forKey: .required) try container.encodeIfPresent(required, forKey: .required)
try container.encodeIfPresent(requiredGroups, forKey: .requiredGroups)
} }
} }

View File

@ -1,5 +1,5 @@
// //
// CaretButton.swift // CaretLink.swift
// MVMCoreUI // MVMCoreUI
// //
// Created by Kolli, Praneeth on 1/5/18. // Created by Kolli, Praneeth on 1/5/18.
@ -8,7 +8,7 @@
// //
open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, ModelMoleculeViewProtocol { open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol {
//------------------------------------------------------ //------------------------------------------------------
// MARK: - Constants // MARK: - Constants
@ -49,7 +49,9 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
didSet { changeCaretColor() } didSet { changeCaretColor() }
} }
public func updateView(_ size: CGFloat) { } public override func updateView(_ size: CGFloat) {
titleLabel?.font = MFStyler.fontB1()
}
//------------------------------------------------------ //------------------------------------------------------
// MARK: - Methods // MARK: - Methods
@ -61,10 +63,18 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
setTitleColor(disabledColor, for: .disabled) setTitleColor(disabledColor, for: .disabled)
if let rightCaretView = rightView as? CaretView { if let rightCaretView = rightView as? CaretView {
rightCaretView.enabledColor = enabledColor
rightCaretView.disabledColor = disabledColor
rightCaretView.isEnabled = isEnabled rightCaretView.isEnabled = isEnabled
} }
} }
private func createCaretView() -> CaretView {
let caret = CaretView()
caret.lineWidth = 1.5
return caret
}
private func addCaretImageView() { private func addCaretImageView() {
rightView?.removeFromSuperview() rightView?.removeFromSuperview()
@ -75,7 +85,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
let edgeInsets: UIEdgeInsets = contentEdgeInsets let edgeInsets: UIEdgeInsets = contentEdgeInsets
contentEdgeInsets = UIEdgeInsets(top: edgeInsets.top, left: edgeInsets.left, bottom: edgeInsets.bottom, right: 4 + width) contentEdgeInsets = UIEdgeInsets(top: edgeInsets.top, left: edgeInsets.left, bottom: edgeInsets.bottom, right: 4 + width)
let caretView: UIView = rightView ?? CaretView() let caretView: UIView = rightView ?? createCaretView()
rightView = caretView rightView = caretView
rightView?.translatesAutoresizingMaskIntoConstraints = false rightView?.translatesAutoresizingMaskIntoConstraints = false
addSubview(caretView) addSubview(caretView)
@ -115,33 +125,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
setTitleColor(disabledColor, for: .disabled) setTitleColor(disabledColor, for: .disabled)
} }
@objc public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
setWithActionMap(json, delegateObject: delegateObject, additionalData: additionalData)
guard let dictionary = json else { return }
if let title = dictionary.optionalStringForKey(KeyTitle) {
setTitle(title, for: .normal)
}
if let disableButtonAsAny = dictionary[KeyDisableButton], let isDisabled = disableButtonAsAny as? Bool {
isEnabled = !isDisabled
}
if let backgroundColorHex = dictionary[KeyBackgroundColor] as? String {
backgroundColor = UIColor.mfGet(forHex: backgroundColorHex)
}
if let enabledColorHex = dictionary["enabledColor"] as? String {
enabledColor = UIColor.mfGet(forHex: enabledColorHex)
}
if let disabledColorHex = dictionary["disabledColor"] as? String {
disabledColor = UIColor.mfGet(forHex: disabledColorHex)
}
}
public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let caretLinkModel = model as? CaretLinkModel else { return } guard let caretLinkModel = model as? CaretLinkModel else { return }
if let color = caretLinkModel.backgroundColor { if let color = caretLinkModel.backgroundColor {
backgroundColor = color.uiColor backgroundColor = color.uiColor
@ -163,7 +147,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
return .leading return .leading
} }
public class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 10 return 10.5
} }
} }

View File

@ -9,14 +9,14 @@
import Foundation import Foundation
import MVMCore import MVMCore
public class CaretLinkModel: MoleculeModelProtocol { public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol {
public static var identifier: String = "caretLink" public static var identifier: String = "caretLink"
public var backgroundColor: Color? public var backgroundColor: Color?
public var title: String public var title: String
public var action: ActionModelProtocol public var action: ActionModelProtocol
public var enabledColor: Color = Color(uiColor: .black) public var enabledColor: Color = Color(uiColor: .black)
public var disabledColor: Color? = Color(uiColor: .mfSilver()) public var disabledColor: Color? = Color(uiColor: .mfSilver())
public var enabled: Bool = true public var enabled = true
public init(title: String, action: ActionModelProtocol) { public init(title: String, action: ActionModelProtocol) {
self.title = title self.title = title

View File

@ -46,7 +46,7 @@ import UIKit
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
} }
public static func estimatedHeight(forRow molecule: ModuleMoleculeModel?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 31.0 return 31.0
} }
} }

View File

@ -8,7 +8,7 @@
import UIKit import UIKit
public class LinkModel: MoleculeModelProtocol { public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
public static var identifier: String = "link" public static var identifier: String = "link"
public var backgroundColor: Color? public var backgroundColor: Color?
public var title: String public var title: String

View File

@ -0,0 +1,179 @@
//
// PillButton.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 1/28/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import UIKit
open class PillButton: Button, MVMCoreUIViewConstrainingProtocol, FormValidationEnableDisableProtocol {
// Used to size the button.
var size = MVMCoreUIUtility.getWidth()
var buttonModel: ButtonModel? {
get { return model as? ButtonModel }
}
// Need to re-style on set.
open override var isEnabled: Bool {
didSet {
style()
}
}
private enum ButtonHeight: CGFloat {
case tiny = 20
case standard = 42
}
/// The primary styling for a button. Should be used for main buttons
public func stylePrimary() {
setTitleColor(.white, for: .normal)
setTitleColor(.white, for: .disabled)
layer.borderWidth = 0
if isEnabled {
backgroundColor = .black
} else {
backgroundColor = .mvmCoolGray6
}
}
/// The secondary styling for a button. Should be used for secondary buttons
public func styleSecondary() {
setTitleColor(.black, for: .normal)
setTitleColor(.mvmCoolGray6, for: .disabled)
backgroundColor = .clear
layer.borderWidth = 1
if isEnabled {
layer.borderColor = UIColor.black.cgColor
} else {
layer.borderColor = UIColor.mvmCoolGray6.cgColor
}
}
/// Styles the button based on the model style
private func style() {
switch buttonModel?.style {
case .secondary:
styleSecondary()
default:
stylePrimary()
}
if let titleColor = buttonModel?.textColor {
setTitleColor(titleColor.uiColor, for: .normal)
}
if let disabledTitleColor = buttonModel?.disabledTextColor {
setTitleColor(disabledTitleColor.uiColor, for: .disabled)
}
if isEnabled {
if let fillColor = buttonModel?.fillColor {
backgroundColor = fillColor.uiColor
}
if let borderColor = buttonModel?.borderColor {
layer.borderWidth = 1
layer.borderColor = borderColor.cgColor
}
} else {
if let fillColor = buttonModel?.disabledFillColor {
backgroundColor = fillColor.uiColor
}
if let borderColor = buttonModel?.disabledBorderColor {
layer.borderWidth = 1
layer.borderColor = borderColor.cgColor
}
}
}
private func getInnerPadding() -> CGFloat {
return getHeight() / 2.0
}
private func getHeight() -> CGFloat {
PillButton.getHeight(for: buttonModel?.size, size: size)
}
public static func getHeight(for buttonSize: ButtonSize?, size: CGFloat) -> CGFloat {
switch buttonSize {
case .tiny:
return MFSizeObject(standardSize: ButtonHeight.tiny.rawValue, standardiPadPortraitSize: 34, iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? ButtonHeight.tiny.rawValue
default:
return MFSizeObject(standardSize: ButtonHeight.standard.rawValue, standardiPadPortraitSize: 46, iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? ButtonHeight.standard.rawValue
}
}
private func getMinimumWidth() -> CGFloat {
switch buttonModel?.size {
case .tiny:
return MFSizeObject(standardSize: 49.0, standardiPadPortraitSize: 90.0, iPadProLandscapeSize: 135.0)?.getValueBased(onSize: size) ?? 49.0
default:
return 151.0
}
}
open override var intrinsicContentSize: CGSize {
let size = super.intrinsicContentSize
let width = size.width + (2 * getInnerPadding())
return CGSize(width: max(width, getMinimumWidth()), height: getHeight())
}
// MARK: - ModelMoleculeViewProtocol
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
// The button will get styled in the enable check in super.
super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? ButtonModel else { return }
setTitle(model.title, for: .normal)
if let required = model.required,
required {
FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol)
}
}
open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
PillButton.getHeight(for: (molecule as? ButtonModel)?.size, size: MVMCoreUIUtility.getWidth())
}
// MARK: - MVMCoreViewProtocol
open override func updateView(_ size: CGFloat) {
super.updateView(size)
self.size = size
invalidateIntrinsicContentSize()
switch buttonModel?.size {
case .tiny:
titleLabel?.font = MFFonts.mfFont75Bd(11 * (intrinsicContentSize.height / ButtonHeight.tiny.rawValue))
default:
titleLabel?.font = MFFonts.mfFont75Bd(13 * (intrinsicContentSize.height / ButtonHeight.standard.rawValue))
}
layer.cornerRadius = getInnerPadding()
}
open override func setupView() {
super.setupView()
titleLabel?.numberOfLines = 1
titleLabel?.lineBreakMode = .byTruncatingTail
titleLabel?.textAlignment = .center
contentHorizontalAlignment = .center
stylePrimary()
}
// MARK: - MVMCoreUIViewConstrainingProtocol
open func horizontalAlignment() -> UIStackView.Alignment {
return .center
}
// MARK: - FormValidationEnableDisableProtocol
public func isValidationRequired() -> Bool {
return buttonModel?.required ?? false
}
public func requiredGroups() -> [String]? {
return buttonModel?.requiredGroups
}
public func enableField(_ enable: Bool) {
isEnabled = isValidationRequired() ? enable : true
}
}

View File

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

View File

@ -25,7 +25,7 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
open private(set) var textField: TextField = { open private(set) var textField: TextField = {
let textField = TextField(frame: .zero) let textField = TextField()
textField.isAccessibilityElement = true textField.isAccessibilityElement = true
textField.setContentCompressionResistancePriority(.required, for: .vertical) textField.setContentCompressionResistancePriority(.required, for: .vertical)
textField.font = MFStyler.fontForTextField() textField.font = MFStyler.fontForTextField()
@ -58,7 +58,7 @@ import UIKit
get { return super.isEnabled } get { return super.isEnabled }
set (enabled) { set (enabled) {
super.isEnabled = enabled super.isEnabled = enabled
DispatchQueue.main.async { [weak self] in DispatchQueue.main.async { [weak self] in
guard let self = self else { return } guard let self = self else { return }
@ -99,7 +99,7 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
public var validationBlock: ((_ value: String?) -> Bool)? public var validationBlock: ((_ value: String?) -> Bool)?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Delegate Properties // MARK: - Delegate Properties
//-------------------------------------------------- //--------------------------------------------------
@ -169,6 +169,9 @@ import UIKit
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16) textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16)
textFieldTrailingConstraint?.isActive = true textFieldTrailingConstraint?.isActive = true
textField.addTarget(self, action: #selector(startEditing), for: .editingDidBegin)
textField.addTarget(self, action: #selector(dismissFieldInput(_:)), for: .editingDidEnd)
let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing)) let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing))
entryFieldContainer.addGestureRecognizer(tap) entryFieldContainer.addGestureRecognizer(tap)
@ -225,7 +228,7 @@ import UIKit
/// Validates the text of the entry field. /// Validates the text of the entry field.
@discardableResult @discardableResult
@objc public func validateTextField() -> Bool { @objc public func validateTextField() -> Bool {
isValid = validationBlock?(text) ?? true isValid = validationBlock?(text) ?? true
if isValid { if isValid {
@ -277,7 +280,7 @@ import UIKit
guard let model = model as? TextEntryFieldModel else { return } guard let model = model as? TextEntryFieldModel else { return }
FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol)
textColor.enabled = model.enabledTextColor?.uiColor textColor.enabled = model.enabledTextColor?.uiColor
textColor.disabled = model.disabledTextColor?.uiColor textColor.disabled = model.disabledTextColor?.uiColor
text = model.text text = model.text

View File

@ -31,7 +31,7 @@ import UIKit
view.translatesAutoresizingMaskIntoConstraints = false view.translatesAutoresizingMaskIntoConstraints = false
addSubview(view) addSubview(view)
view.backgroundColor = progressObject.progressColor.uiColor view.backgroundColor = progressObject.progressColor.uiColor
view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.progress).isActive = true view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.progress/100.0).isActive = true
view.leadingAnchor.constraint(equalTo: previous?.trailingAnchor ?? leadingAnchor).isActive = true view.leadingAnchor.constraint(equalTo: previous?.trailingAnchor ?? leadingAnchor).isActive = true
previous = view previous = view
NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false)

View File

@ -91,6 +91,10 @@ public typealias ButtonAction = (Button) -> ()
if let backgroundColor = model?.backgroundColor { if let backgroundColor = model?.backgroundColor {
self.backgroundColor = backgroundColor.uiColor self.backgroundColor = backgroundColor.uiColor
} }
guard let model = model as? ButtonModelProtocol else { return }
isEnabled = model.enabled
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
} }
open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {

View File

@ -0,0 +1,14 @@
//
// ButtonModelProtocol.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 1/28/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol ButtonModelProtocol: EnableableModelProtocol {
var enabled: Bool { get set }
var action: ActionModelProtocol { get set }
}

View File

@ -6,11 +6,11 @@
// Copyright © 2019 Verizon Wireless. All rights reserved. // Copyright © 2019 Verizon Wireless. All rights reserved.
// //
import UIKit import UIKit
public typealias ColorHexTuple = (uiColor: UIColor, hex: String) public typealias ColorHexTuple = (uiColor: UIColor, hex: String)
extension UIColor { extension UIColor {
/// Dictionary to access brand approved colors by name. /// Dictionary to access brand approved colors by name.
@ -25,6 +25,7 @@ extension UIColor {
"coolGray1": (.mvmCoolGray1, "#F6F6F6"), "coolGray1": (.mvmCoolGray1, "#F6F6F6"),
"coolGray3": (.mvmCoolGray3, "#D8DADA"), "coolGray3": (.mvmCoolGray3, "#D8DADA"),
"coolGray6": (.mvmCoolGray6, "#747676"), "coolGray6": (.mvmCoolGray6, "#747676"),
"coolGray10": (.mvmCoolGray10, "#333333"),
"vzupGold": (.vzupGold, "#B89B56"), "vzupGold": (.vzupGold, "#B89B56"),
"vzupYellow1": (.vzupYellow1, "#F9D542"), "vzupYellow1": (.vzupYellow1, "#F9D542"),
"vzupYellow2": (.vzupYellow2, "#F4CA53"), "vzupYellow2": (.vzupYellow2, "#F4CA53"),
@ -67,6 +68,9 @@ extension UIColor {
/// HEX: #747676 /// HEX: #747676
public static let mvmCoolGray6 = UIColor.color8Bits(red: 116, green: 118, blue: 118) public static let mvmCoolGray6 = UIColor.color8Bits(red: 116, green: 118, blue: 118)
/// HEX: #333333
public static let mvmCoolGray10 = UIColor.grayscale(rgb: 51)
//-------------------------------------------------- //--------------------------------------------------
// MARK: - VZ UP Brand // MARK: - VZ UP Brand
//-------------------------------------------------- //--------------------------------------------------
@ -196,15 +200,4 @@ extension UIColor {
return nil return nil
} }
public class func getColorAndHexFromName(_ name: String) -> ColorHexTuple? {
for row in names {
if name == row.key {
return row.value
}
}
return nil
}
} }

View File

@ -56,7 +56,7 @@ public final class Color: Codable {
} }
init?(name: String) { init?(name: String) {
guard let colorTuple = UIColor.getColorAndHexFromName(name) else { return nil } guard let colorTuple = UIColor.names[name] else { return nil }
self.uiColor = colorTuple.uiColor self.uiColor = colorTuple.uiColor
self.hex = colorTuple.hex self.hex = colorTuple.hex
determineRGBA() determineRGBA()
@ -73,7 +73,7 @@ public final class Color: Codable {
if colorString.hasPrefix("#") { if colorString.hasPrefix("#") {
hex = colorString.replacingOccurrences(of: "#", with: "") hex = colorString.replacingOccurrences(of: "#", with: "")
} else { } else {
guard let hex = UIColor.getColorAndHexFromName(colorString)?.hex else { throw ColorError.badName(reason: "Check the spelling of your color.") } guard let hex = UIColor.names[colorString]?.hex else { throw ColorError.badName(reason: "Check the spelling of your color.") }
self.hex = hex.replacingOccurrences(of: "#", with: "") self.hex = hex.replacingOccurrences(of: "#", with: "")
name = colorString name = colorString
} }

View File

@ -7,6 +7,7 @@
// //
#import "TopLabelsAndBottomButtonsTableViewController.h" #import "TopLabelsAndBottomButtonsTableViewController.h"
#import <MVMCoreUI/PrimaryButtonView.h>
#import <MVMCoreUI/MVMCoreUIUtility.h> #import <MVMCoreUI/MVMCoreUIUtility.h>
#import <MVMCoreUI/StackableViewController.h> #import <MVMCoreUI/StackableViewController.h>
#import <MVMCoreUI/MVMCoreUICommonViewsUtility.h> #import <MVMCoreUI/MVMCoreUICommonViewsUtility.h>
@ -121,7 +122,7 @@
// Sets up the buttons/button. // Sets up the buttons/button.
NSDictionary *primaryButtonDictionary = [self primaryButtonMap]; NSDictionary *primaryButtonDictionary = [self primaryButtonMap];
NSDictionary *secondaryButtonDictionary = [self secondaryButtonMap]; NSDictionary *secondaryButtonDictionary = [self secondaryButtonMap];
TwoButtonView *buttonView = [[TwoButtonView alloc] initWithPrimaryButtonMap:primaryButtonDictionary secondaryButtonMap:secondaryButtonDictionary delegateObject:[self delegateObject] additionalData:nil]; PrimaryButtonView *buttonView = [[PrimaryButtonView alloc] initWithPrimaryButtonMap:primaryButtonDictionary secondaryButtonMap:secondaryButtonDictionary actionDelegate:self additionalData:nil buttonDelegate:self];
self.secondaryButton = buttonView.secondaryButton; self.secondaryButton = buttonView.secondaryButton;
self.primaryButton = buttonView.primaryButton; self.primaryButton = buttonView.primaryButton;
@ -439,16 +440,16 @@
- (void)setPrimaryLeftButtonHidden:(BOOL)left rightButtonHidden:(BOOL)right { - (void)setPrimaryLeftButtonHidden:(BOOL)left rightButtonHidden:(BOOL)right {
if ([self.bottomView isKindOfClass:[TwoButtonView class]]) { if ([self.bottomView isKindOfClass:[PrimaryButtonView class]]) {
TwoButtonView *buttonView = (TwoButtonView *)self.bottomView; PrimaryButtonView *buttonView = (PrimaryButtonView *)self.bottomView;
if (right && !left) { if (right && !left) {
[buttonView hideRightButton]; [buttonView hidePrimaryRightButton];
} else if (!right && left) { } else if (!right && left) {
[buttonView hideLeftButton]; [buttonView hidePrimaryLeftButton];
} else if (right && left) { } else if (right && left) {
[buttonView hideBothButtons]; [buttonView hideBothPrimaryButtons];
} else if (!right && !left) { } else if (!right && !left) {
[buttonView showBothButtons]; [buttonView showBothPrimaryButtons];
} }
} }
} }

View File

@ -7,6 +7,7 @@
// //
#import "TopLabelsAndBottomButtonsViewController.h" #import "TopLabelsAndBottomButtonsViewController.h"
#import <MVMCoreUI/PrimaryButtonView.h>
#import <MVMCoreUI/MFSizeObject.h> #import <MVMCoreUI/MFSizeObject.h>
#import <MVMCoreUI/MVMCoreUICommonViewsUtility.h> #import <MVMCoreUI/MVMCoreUICommonViewsUtility.h>
#import <MVMCoreUI/UIColor+MFConvenience.h> #import <MVMCoreUI/UIColor+MFConvenience.h>
@ -81,18 +82,18 @@
} }
if (!self.customBottemView) { if (!self.customBottemView) {
TwoButtonView *buttonView = (TwoButtonView *)self.bottomView; PrimaryButtonView *buttonView = (PrimaryButtonView *)self.bottomView;
if (self.secondaryButton || self.primaryButton) { if (self.secondaryButton || self.primaryButton) {
UIEdgeInsets paddingForBottomButtons = [self paddingForBottomButtons]; UIEdgeInsets paddingForBottomButtons = [self paddingForBottomButtons];
[buttonView setLeftPinConstant:paddingForBottomButtons.left]; buttonView.leftPin.constant = paddingForBottomButtons.left;
[buttonView setRightPinConstant:paddingForBottomButtons.right]; buttonView.rightPin.constant = paddingForBottomButtons.right;
buttonView.topPin.constant = paddingForBottomButtons.top; buttonView.topPin.constant = paddingForBottomButtons.top;
buttonView.bottomPin.constant = paddingForBottomButtons.bottom; buttonView.bottomPin.constant = paddingForBottomButtons.bottom;
} else { } else {
buttonView.topPin.constant = 0; buttonView.topPin.constant = 0;
buttonView.bottomPin.constant = 0; buttonView.bottomPin.constant = 0;
[buttonView setLeftPinConstant:0]; buttonView.leftPin.constant = 0;
[buttonView setRightPinConstant:0]; buttonView.rightPin.constant = 0;
} }
} }
} }
@ -138,7 +139,7 @@
// Sets up the buttons/button. // Sets up the buttons/button.
NSDictionary *primaryButtonDictionary = [self primaryButtonMap]; NSDictionary *primaryButtonDictionary = [self primaryButtonMap];
NSDictionary *secondaryButtonDictionary = [self secondaryButtonMap]; NSDictionary *secondaryButtonDictionary = [self secondaryButtonMap];
TwoButtonView *buttonView = [[TwoButtonView alloc] initWithPrimaryButtonMap:primaryButtonDictionary secondaryButtonMap:secondaryButtonDictionary delegateObject:[self delegateObject] additionalData:nil]; PrimaryButtonView *buttonView = [[PrimaryButtonView alloc] initWithPrimaryButtonMap:primaryButtonDictionary secondaryButtonMap:secondaryButtonDictionary actionDelegate:self additionalData:nil buttonDelegate:self];
self.secondaryButton = buttonView.secondaryButton; self.secondaryButton = buttonView.secondaryButton;
self.primaryButton = buttonView.primaryButton; self.primaryButton = buttonView.primaryButton;
bottomView = buttonView; bottomView = buttonView;

View File

@ -0,0 +1,26 @@
//
// MFCaretButton.h
// MobileFirstFramework
//
// Created by Kolli, Praneeth on 1/5/18.
// Copyright © 2018 Verizon Wireless. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <MVMCoreUI/MFCustomButton.h>
@interface MFCaretButton : MFCustomButton
@property (nullable, nonatomic, strong) UIView *rightView;
@property (nullable, nonatomic, strong) NSNumber *rightViewHeight;
@property (nullable, nonatomic, strong) NSNumber *rightViewWidth;
-(void)updateCaretSpacing:(CGFloat)spacing;
/* The fill color of the Caret and titleLabel. The default is blackColor */
-(void)setEnableCaretColor:(nullable UIColor *)enableCaretColor;
/* The fill color of the Caret and titleLabel. The default is mfSilver */
-(void)setDisabledCaretColor:(nullable UIColor *)disabledCaretColor;
@end

View File

@ -0,0 +1,113 @@
//
// MFCaretButton.m
// MobileFirstFramework
//
// Created by Kolli, Praneeth on 1/5/18.
// Copyright © 2018 Verizon Wireless. All rights reserved.
//
#import "MFCaretButton.h"
#import "MFCaretView.h"
#import "UIColor+MFConvenience.h"
@interface MFCaretButton ()
@property (nonatomic, strong) UIColor *enableColor;
@property (nonatomic, strong) UIColor *disabledColor;
@property (nonatomic, strong) NSLayoutConstraint *caretSpacingConstraint;
@end
@implementation MFCaretButton
CGFloat const CaretViewHeight = 10.8f;
CGFloat const CaretViewWidth = 6.6f;
- (void)layoutSubviews {
[self addCaretImageView];
[super layoutSubviews];
}
- (void)setEnabled:(BOOL)enabled {
[super setEnabled:enabled];
[self changeCaretColor];
}
- (void)changeCaretColor {
[self setTitleColor:self.enableColor forState:UIControlStateNormal];
[self setTitleColor:self.disabledColor forState:UIControlStateDisabled];
if ([self.rightView isKindOfClass:[MFCaretView class]]) {
MFCaretView *caretView = (MFCaretView *)self.rightView;
if (self.enabled) {
[caretView setLineColor:self.enableColor];
} else {
[caretView setLineColor:self.disabledColor];
}
}
}
- (void)addCaretImageView {
[self.rightView removeFromSuperview];
UIEdgeInsets edgeInsets = self.contentEdgeInsets;
CGFloat rightInset = self.rightViewWidth?self.rightViewWidth.floatValue:CaretViewWidth;
UIEdgeInsets newInsets = UIEdgeInsetsMake(edgeInsets.top, edgeInsets.left, edgeInsets.bottom, 4 + rightInset);
self.contentEdgeInsets = newInsets;
UIView *caretViewIs = self.rightView;
if (!self.rightView) {
caretViewIs = [[MFCaretView alloc]init];
self.rightView = caretViewIs;
}
self.rightView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:self.rightView];
CGFloat width = self.rightViewWidth?self.rightViewWidth.floatValue:CaretViewWidth;
NSLayoutConstraint *caretViewWidthConstraint = [NSLayoutConstraint constraintWithItem:caretViewIs attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:width];
caretViewWidthConstraint.active = YES;
CGFloat height = self.rightViewHeight?self.rightViewHeight.floatValue:CaretViewHeight;
NSLayoutConstraint *caretViewHeightConstraint = [NSLayoutConstraint constraintWithItem:caretViewIs attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:height];
caretViewHeightConstraint.active = YES;
NSLayoutConstraint *caretLabelSpacing = [NSLayoutConstraint constraintWithItem:caretViewIs attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.titleLabel attribute:NSLayoutAttributeRight multiplier:1.0 constant:4.0];
caretLabelSpacing.active = YES;
self.caretSpacingConstraint = caretLabelSpacing;
NSLayoutConstraint *caretCenterY = [NSLayoutConstraint constraintWithItem:caretViewIs attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0];
caretCenterY.active = YES;
NSLayoutConstraint *caretLabelRightPin = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:caretViewIs attribute:NSLayoutAttributeRight multiplier:1.0 constant:0];
caretLabelRightPin.active = YES;
self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
//set correct color after layout
[self changeCaretColor];
}
- (void)updateCaretSpacing:(CGFloat)spacing {
if (self.caretSpacingConstraint != nil) {
self.caretSpacingConstraint.constant = spacing;
}
}
- (void)setEnableCaretColor:(UIColor *)enableCaretColor {
self.enableColor = enableCaretColor;
[self changeCaretColor];
}
- (void)setDisabledCaretColor:(UIColor *)disabledCaretColor {
self.disabledColor = disabledCaretColor;
[self changeCaretColor];
}
@synthesize enableColor = _enableColor;
- (UIColor *)enableColor {
if (!_enableColor) {
_enableColor = [UIColor blackColor];
}
return _enableColor;
}
@synthesize disabledColor = _disabledColor;
- (UIColor *)disabledColor {
if (!_disabledColor) {
_disabledColor = [UIColor mfSilver];
}
return _disabledColor;
}
@end

View File

@ -0,0 +1,16 @@
//
// MFCaretView.h
// MobileFirstFramework
//
// Created by Kolli, Praneeth on 1/5/18.
// Copyright © 2018 Verizon Wireless. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface MFCaretView : UIView
@property (strong, nonatomic, readonly) UIColor *strokeColor;
- (instancetype)initWithLineWidth:(CGFloat)lineWidth;
- (void)setLineColor:(UIColor *)color;
@end

View File

@ -0,0 +1,93 @@
//
// MFCaretView.m
// MobileFirstFramework
//
// Created by Kolli, Praneeth on 1/5/18.
// Copyright © 2018 Verizon Wireless. All rights reserved.
//
#import "MFCaretView.h"
#import "UIColor+MFConvenience.h"
@interface MFCaretView ()
@property (strong, nonatomic, readwrite) UIColor *strokeColor;
@property (nonatomic) NSNumber *lineWidth;
@end
@implementation MFCaretView
- (instancetype)init {
self = [super init];
if (self) {
// Initialization code
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.strokeColor = [UIColor blackColor];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.strokeColor = [UIColor blackColor];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
// Initialization code
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.strokeColor = [UIColor blackColor];
}
return self;
}
- (instancetype)initWithLineWidth:(CGFloat)lineWidth {
if (self = [super init]) {
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.lineWidth = @(lineWidth);
self.strokeColor = [UIColor blackColor];
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing Caret
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
CGFloat lineWidth;
if (self.lineWidth) {
lineWidth = self.lineWidth.floatValue;
} else {
lineWidth = self.frame.size.width/2.6;
}
UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:CGPointMake(lineWidth/2.0, 0.0)];
[path addLineToPoint:CGPointMake(self.frame.size.width, self.frame.size.height/2.0)];
[path addLineToPoint:CGPointMake(lineWidth/2.0, self.frame.size.height)];
[path addLineToPoint:CGPointMake(0.0, self.frame.size.height-lineWidth/2.0)];
[path addLineToPoint:CGPointMake(self.frame.size.width-lineWidth, self.frame.size.height/2.0)];
[path addLineToPoint:CGPointMake(0.0, lineWidth/2.0)];
[path addLineToPoint:CGPointMake(lineWidth/2.0, 0.0)];
[self.strokeColor setFill];
[path fill];
[path closePath];
[self setBackgroundColor:[UIColor clearColor]];
}
- (void)setLineColor:(UIColor *)color {
self.strokeColor = color;
[self setNeedsDisplay];
}
@end

View File

@ -0,0 +1,63 @@
//
// PrimaryButtonView.h
// myverizon
//
// Created by Scott Pfeil on 12/11/15.
// Copyright © 2015 Verizon Wireless. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <MVMCoreUI/ViewConstrainingView.h>
#import <MVMCoreUI/PrimaryButton.h>
@interface PrimaryButtonView : ViewConstrainingView
// Set when there is one button or it is the right button when there are two.
@property (nullable, weak, nonatomic) PrimaryButton *primaryButton;
// The left button when there are two buttons.
@property (nullable, weak, nonatomic) PrimaryButton *secondaryButton;
// Inits with a single button.
- (nonnull instancetype)initButtonSmall:(BOOL)small enabled:(BOOL)enabled;
// Inits with two buttons.
- (nonnull instancetype)initWithTwoButtons;
// Legacy: Sets up with whatever is in the passed in button map. (could be 0, 1, or 2 buttons)
- (nonnull instancetype)initButtonSmall:(BOOL)small buttonMap:(nullable NSDictionary *)buttonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate;
- (nonnull instancetype)initWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate;
- (void)setupWithButtonMap:(nullable NSDictionary *)buttonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate;
- (void)setupWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate;
// Sets up with two buttons.
- (void)setupWithTwoButtons;
// For subclassing, just returns the button.
- (nonnull id)createButton;
// Change the alignment of the button
- (void)alignLeft;
- (void)alignCenter;
- (void)alignRight;
- (void)alignFill;//default behavior
// Show/hide left and right primary buttons. This does not impact the vertical space of the view.
- (void)hidePrimaryLeftButton;
- (void)hidePrimaryRightButton;
- (void)showBothPrimaryButtons;
- (void)hideBothPrimaryButtons;
- (void)removeSubviews;
// update with delegateObject
- (nonnull instancetype)initButtonSmall:(BOOL)small buttonMap:(nullable NSDictionary *)buttonMap delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
- (nonnull instancetype)initWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
- (void)setupWithButtonMap:(nullable NSDictionary *)buttonMap delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
- (void)setupWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
@end

View File

@ -0,0 +1,392 @@
//
// PrimaryButtonView.m
// myverizon
//
// Created by Scott Pfeil on 12/11/15.
// Copyright © 2015 Verizon Wireless. All rights reserved.
//
#import "PrimaryButtonView.h"
#import <MVMCore/NSDictionary+MFConvenience.h>
#import <MVMCore/MVMCoreDispatchUtility.h>
#import <MVMCore/MVMCoreJSONConstants.h>
#import "MVMCoreUICommonViewsUtility.h"
#import "MVMCoreUIConstants.h"
#import "UIColor+MFConvenience.h"
#import <MVMCoreUI/MVMCoreUI-Swift.h>
@import MVMCore.Swift;
@interface PrimaryButtonView ()
@property (weak, nonatomic) UIView *twoButtonView;
@property (weak, nonatomic) NSLayoutConstraint *alignCenterPin;
@property (weak, nonatomic) NSLayoutConstraint *alignCenterLeftPin;
@property (weak, nonatomic) NSLayoutConstraint *alignCenterRightPin;
@property (weak, nonatomic) NSLayoutConstraint *height;
@property (nonatomic, strong) NSArray<NSLayoutConstraint *> *horizontalConstraints;
@end
@implementation PrimaryButtonView
- (void)updateView:(CGFloat)size {
[super updateView:size];
[MVMCoreDispatchUtility performBlockOnMainThread:^{
[self.primaryButton updateView:size];
[self.secondaryButton updateView:size];
}];
}
- (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
[super setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
NSString *backgroundColorString = [json string:@"backgroundColor"];
if (backgroundColorString) {
self.backgroundColor = [UIColor mfGetColorForHex:backgroundColorString];
}
NSDictionary *primaryButtonMap = [json dict:@"primaryButton"];
NSDictionary *secondaryButtonMap = [json dict:@"secondaryButton"];
[self setupUIWithPrimaryButtonMap:primaryButtonMap secondaryButtonMap:secondaryButtonMap];
[self.primaryButton setAsStandardCustom];
[self.secondaryButton setAsSecondaryCustom];
[self.primaryButton setWithJSON:primaryButtonMap delegateObject:delegateObject additionalData:additionalData];
[self.secondaryButton setWithJSON:secondaryButtonMap delegateObject:delegateObject additionalData:additionalData];
}
#pragma mark - Inits
- (instancetype)init {
if (self = [super init]) {
self.backgroundColor = [UIColor clearColor];
self.translatesAutoresizingMaskIntoConstraints = NO;
[self setupWithSingleButton];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
self.backgroundColor = [UIColor clearColor];
self.translatesAutoresizingMaskIntoConstraints = NO;
[self setupWithSingleButton];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor clearColor];
self.translatesAutoresizingMaskIntoConstraints = NO;
[self setupWithSingleButton];
}
return self;
}
- (nonnull instancetype)initButtonSmall:(BOOL)small enabled:(BOOL)enabled {
if (self = [self init]) {
[self.primaryButton setAsSmallButton:small];
[self.primaryButton setEnabled:enabled];
}
return self;
}
- (nonnull instancetype)initWithTwoButtons {
if (self = [self init]) {
[self setupWithTwoButtons];
}
return self;
}
#pragma mark - Legacy Setup
- (nonnull instancetype)initButtonSmall:(BOOL)small buttonMap:(nullable NSDictionary *)buttonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate {
if (self = [self init]) {
[self setupWithButtonMap:buttonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
[self.primaryButton setAsSmallButton:small];
[self.secondaryButton setAsSmallButton:small];
}
return self;
}
- (nonnull instancetype)initWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate {
if (self = [self init]) {
[self setupWithPrimaryButtonMap:primaryButtonMap secondaryButtonMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
}
return self;
}
- (void)setupWithButtonMap:(nullable NSDictionary *)buttonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate {
NSDictionary *secondaryButtonMap = [buttonMap dict:KeySecondaryButton];
NSDictionary *primaryButtonMap = [buttonMap dict:KeyPrimaryButton];
[self setupWithPrimaryButtonMap:primaryButtonMap secondaryButtonMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
}
- (void)setupWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate {
[self setupUIWithPrimaryButtonMap:primaryButtonMap secondaryButtonMap:secondaryButtonMap];
if (primaryButtonMap && secondaryButtonMap) {
[self.primaryButton setWithActionMap:primaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
[self.secondaryButton setWithActionMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
} else if (primaryButtonMap) {
[self.primaryButton setWithActionMap:primaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
self.primaryButton.bordered = NO;
} else {
[self.primaryButton setWithActionMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
self.primaryButton.bordered = YES;
}
}
#pragma mark - Setup
- (void)setupUIWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap {
if (primaryButtonMap && secondaryButtonMap) {
self.height.active = NO;
// Setup with two buttons
if (!self.primaryButton || !self.secondaryButton) {
[self removeSubviews];
self.twoButtonView = nil;
[self setupWithTwoButtons];
}
} else if (primaryButtonMap || secondaryButtonMap) {
self.height.active = NO;
// Setup with one button.
if (!self.primaryButton || self.secondaryButton) {
[self removeSubviews];
self.primaryButton = nil;
self.secondaryButton = nil;
[self setupWithSingleButton];
}
} else {
[self removeSubviews];
if (!self.height) {
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0];
height.active = YES;
self.height = height;
}
}
}
- (id)createButton {
return [PrimaryButton primaryButton:NO];
}
- (void)setupWithTwoButtons {
if (self.primaryButton) {
[self.primaryButton removeFromSuperview];
self.primaryButton = nil;
}
if (!self.twoButtonView) {
self.backgroundColor = [UIColor clearColor];
self.translatesAutoresizingMaskIntoConstraints = NO;
UIView *buttonView = [MVMCoreUICommonViewsUtility commonView];
PrimaryButton *leftButton = [PrimaryButton primaryButton];
leftButton.bordered = YES;
leftButton.translatesAutoresizingMaskIntoConstraints = NO;
[buttonView addSubview:leftButton];
self.secondaryButton = leftButton;
PrimaryButton *rightButton = [PrimaryButton primaryButton];
rightButton.translatesAutoresizingMaskIntoConstraints = NO;
[buttonView addSubview:rightButton];
self.primaryButton = rightButton;
[rightButton.widthAnchor constraintEqualToAnchor:leftButton.widthAnchor multiplier:1].active = YES;
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[leftButton]-0-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(leftButton)]];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[rightButton]-0-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(rightButton)]];
self.horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[leftButton]-10-[rightButton]-0-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(leftButton,rightButton)];
[NSLayoutConstraint activateConstraints:self.horizontalConstraints];
[self addSubview:buttonView];
[self setupAlignmentsWithView:buttonView];
self.twoButtonView = buttonView;
[self alignCenter];
}
}
- (void)setupWithSingleButton {
if (!self.primaryButton) {
self.backgroundColor = [UIColor clearColor];
self.translatesAutoresizingMaskIntoConstraints = NO;
PrimaryButton *button = [self createButton];
button.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:button];
self.primaryButton = button;
[self setupAlignmentsWithView:button];
[self alignCenter];
}
}
- (void)setupAlignmentsWithView:(UIView *)view {
// Align left and right constants.
NSLayoutConstraint *leftPin = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];
self.leftPin = leftPin;
leftPin.active = YES;
NSLayoutConstraint *topPin = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
self.topPin = topPin;
topPin.active = YES;
NSLayoutConstraint *bottomPin = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
self.bottomPin = bottomPin;
bottomPin.active = YES;
NSLayoutConstraint *rightPin = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeRight multiplier:1.0 constant:0];
self.rightPin = rightPin;
rightPin.active = YES;
// Center alignments
NSLayoutConstraint *alignCenter = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
self.alignCenterPin = alignCenter;
alignCenter.active = YES;
NSLayoutConstraint *centerLeftPin = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];
self.alignCenterLeftPin = centerLeftPin;
centerLeftPin.active = YES;
NSLayoutConstraint *centerRightPin = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:view attribute:NSLayoutAttributeRight multiplier:1.0 constant:0];
self.alignCenterRightPin = centerRightPin;
centerRightPin.active = YES;
}
#pragma mark - Configuring
- (void)alignLeft {
self.alignCenterPin.active = NO;
self.alignCenterLeftPin.active = NO;
self.alignCenterRightPin.active = YES;
self.leftPin.active = YES;
self.rightPin.active = NO;
}
- (void)alignCenter {
self.alignCenterPin.active = YES;
self.alignCenterLeftPin.active = YES;
self.alignCenterRightPin.active = YES;
self.leftPin.active = NO;
self.rightPin.active = NO;
}
- (void)alignFill {
self.alignCenterPin.active = NO;
self.alignCenterLeftPin.active = NO;
self.alignCenterRightPin.active = NO;
self.leftPin.active = YES;
self.rightPin.active = YES;
}
- (void)alignRight {
self.alignCenterPin.active = NO;
self.alignCenterLeftPin.active = YES;
self.alignCenterRightPin.active = NO;
self.leftPin.active = NO;
self.rightPin.active = YES;
}
- (void)setLeftPinConstant:(CGFloat)constant {
[super setLeftPinConstant:constant];
self.alignCenterLeftPin.constant = constant;
}
- (void)setRightPinConstant:(CGFloat)constant {
[super setRightPinConstant:constant];
self.alignCenterRightPin.constant = constant;
}
- (void)resetConstraints {
[super resetConstraints];
self.primaryButton.enabled = NO;
}
- (void)hidePrimaryLeftButton {
if (!self.secondaryButton.hidden) {
self.secondaryButton.hidden = YES;
PrimaryButton *rightButton = self.primaryButton;
[NSLayoutConstraint deactivateConstraints:self.horizontalConstraints];
self.horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[rightButton]-0-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(rightButton)];
[NSLayoutConstraint activateConstraints:self.horizontalConstraints];
}
}
- (void)hidePrimaryRightButton {
if (!self.primaryButton.hidden) {
self.primaryButton.hidden = YES;
PrimaryButton *leftButton = self.secondaryButton;
[NSLayoutConstraint deactivateConstraints:self.horizontalConstraints];
self.horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[leftButton]-0-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(leftButton)];
[NSLayoutConstraint activateConstraints:self.horizontalConstraints];
}
}
- (void)showBothPrimaryButtons {
self.primaryButton.hidden = NO;
self.secondaryButton.hidden = NO;
PrimaryButton *rightButton = self.primaryButton;
PrimaryButton *leftButton = self.secondaryButton;
[NSLayoutConstraint deactivateConstraints:self.horizontalConstraints];
self.horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[leftButton]-10-[rightButton]-0-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(leftButton,rightButton)];
[NSLayoutConstraint activateConstraints:self.horizontalConstraints];
}
- (void)hideBothPrimaryButtons {
self.primaryButton.hidden = YES;
self.secondaryButton.hidden = YES;
}
- (void)removeSubviews {
for (UIView *view in self.subviews) {
[view removeFromSuperview];
}
}
// update with delegateObject
- (nonnull instancetype)initButtonSmall:(BOOL)small buttonMap:(nullable NSDictionary *)buttonMap delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData {
NSObject<ButtonDelegateProtocol> *buttonDelegate = nil;
NSObject<MVMCoreActionDelegateProtocol> *actionDelegate = delegateObject.actionDelegate;
if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) {
buttonDelegate = ((MVMCoreUIDelegateObject *)delegateObject).buttonDelegate;
}
return [self initButtonSmall:small buttonMap:buttonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
}
- (nonnull instancetype)initWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData {
NSObject<ButtonDelegateProtocol> *buttonDelegate = nil;
NSObject<MVMCoreActionDelegateProtocol> *actionDelegate = delegateObject.actionDelegate;
if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) {
buttonDelegate = ((MVMCoreUIDelegateObject *)delegateObject).buttonDelegate;
}
return [self initWithPrimaryButtonMap:primaryButtonMap secondaryButtonMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
}
- (void)setupWithButtonMap:(nullable NSDictionary *)buttonMap delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData {
NSObject<ButtonDelegateProtocol> *buttonDelegate = nil;
NSObject<MVMCoreActionDelegateProtocol> *actionDelegate = delegateObject.actionDelegate;
if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) {
buttonDelegate = ((MVMCoreUIDelegateObject *)delegateObject).buttonDelegate;
}
[self setupWithButtonMap:buttonMap actionDelegate:actionDelegate additionalData:nil buttonDelegate:buttonDelegate];
}
- (void)setupWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData {
NSObject<ButtonDelegateProtocol> *buttonDelegate = nil;
NSObject<MVMCoreActionDelegateProtocol> *actionDelegate = delegateObject.actionDelegate;
if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) {
buttonDelegate = ((MVMCoreUIDelegateObject *)delegateObject).buttonDelegate;
}
[self setupWithPrimaryButtonMap:primaryButtonMap secondaryButtonMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
}
@end

View File

@ -81,6 +81,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[];
#import <MVMCoreUI/MVMCoreUICheckBox.h> #import <MVMCoreUI/MVMCoreUICheckBox.h>
#import <MVMCoreUI/MVMCoreUISwitch.h> #import <MVMCoreUI/MVMCoreUISwitch.h>
#import <MVMCoreUI/MFRadioButton.h> #import <MVMCoreUI/MFRadioButton.h>
#import <MVMCoreUI/MFCaretView.h>
#pragma mark Buttons #pragma mark Buttons
#import <MVMCoreUI/MFButtonProtocol.h> #import <MVMCoreUI/MFButtonProtocol.h>
@ -88,6 +89,8 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[];
#import <MVMCoreUI/MFCustomButton.h> #import <MVMCoreUI/MFCustomButton.h>
#import <MVMCoreUI/PrimaryButton.h> #import <MVMCoreUI/PrimaryButton.h>
#import <MVMCoreUI/MFTextButton.h> #import <MVMCoreUI/MFTextButton.h>
#import <MVMCoreUI/PrimaryButtonView.h>
#import <MVMCoreUI/MFCaretButton.h>
#pragma mark TextFields #pragma mark TextFields
#import <MVMCoreUI/MFTextField.h> #import <MVMCoreUI/MFTextField.h>

View File

@ -0,0 +1,13 @@
//
// EnableableModelProtocol.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 1/28/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol EnableableModelProtocol {
var enabled: Bool { get set }
}

View File

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

View File

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

View File

@ -60,7 +60,7 @@ import UIKit
bottomSeparatorView?.setStyle(.none) bottomSeparatorView?.setStyle(.none)
} }
public override static func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 80 return 80
} }
} }

View File

@ -171,10 +171,8 @@ import UIKit
guard let model = model as? CornerLabelsModel else { return } guard let model = model as? CornerLabelsModel else { return }
if middleView != nil { if middleView != nil {
(middleView as? ModelMoleculeViewProtocol)?.setWithModel(model, delegateObject, additionalData) (middleView as? ModelMoleculeViewProtocol)?.setWithModel(model, delegateObject, additionalData)
} else { } else if let moleculeModel = model.molecule, let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(moleculeModel, delegateObject) {
if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model.molecule, delegateObject) { addMiddleView(molecule)
addMiddleView(molecule)
}
} }
topLeftLabel.setWithModel(model.topLeftLabel, delegateObject, additionalData) topLeftLabel.setWithModel(model.topLeftLabel, delegateObject, additionalData)

View File

@ -15,9 +15,9 @@ public class CornerLabelsModel: MoleculeModelProtocol {
public var topRightLabel: LabelModel? public var topRightLabel: LabelModel?
public var bottomLeftLabel: LabelModel? public var bottomLeftLabel: LabelModel?
public var bottomRightLabel: LabelModel? public var bottomRightLabel: LabelModel?
public var molecule: MoleculeModelProtocol public var molecule: MoleculeModelProtocol?
init(with molecule: MoleculeModelProtocol) { init(with molecule: MoleculeModelProtocol?) {
self.molecule = molecule self.molecule = molecule
} }
@ -33,7 +33,7 @@ public class CornerLabelsModel: MoleculeModelProtocol {
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
molecule = try typeContainer.decodeMolecule(codingKey: .molecule) molecule = try typeContainer.decodeMoleculeIfPresent(codingKey: .molecule)
topLeftLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .topLeftLabel) topLeftLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .topLeftLabel)
topRightLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .topRightLabel) topRightLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .topRightLabel)
bottomLeftLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .bottomLeftLabel) bottomLeftLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .bottomLeftLabel)

View File

@ -9,9 +9,8 @@
import Foundation import Foundation
@objcMembers public class HeadLineBodyCaretLinkImage: Container { @objcMembers public class HeadLineBodyCaretLinkImage: Container {
let headlineBody = HeadlineBody(frame: .zero) let headlineBody = HeadlineBody(frame: .zero)
let caretButton = CaretButton(frame: .zero) let caretButton = CaretLink(frame: .zero)
let backgroundImageView = MFLoadImageView(pinnedEdges: .all) let backgroundImageView = MFLoadImageView(pinnedEdges: .all)
var spaceBetweenConstant: CGFloat = 104.0
let maxWidth: CGFloat = 350.0 let maxWidth: CGFloat = 350.0
static let heightConstant: CGFloat = 320.0 static let heightConstant: CGFloat = 320.0
var heightConstraint: NSLayoutConstraint? var heightConstraint: NSLayoutConstraint?
@ -44,17 +43,17 @@ import Foundation
headlineBody.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true headlineBody.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
headlineBody.topAnchor.constraint(equalTo: container.topAnchor, constant: 0).isActive = true headlineBody.topAnchor.constraint(equalTo: container.topAnchor, constant: 0).isActive = true
let headLineBodyWidth = headlineBody.widthAnchor.constraint(equalTo: container.widthAnchor, multiplier: 0.85) headlineBody.widthAnchor.constraint(equalTo: container.widthAnchor, multiplier: 0.67).isActive = true
headLineBodyWidth.priority = .defaultHigh let headLineBodyWidth = headlineBody.widthAnchor.constraint(lessThanOrEqualToConstant: maxWidth)
headLineBodyWidth.priority = UILayoutPriority(250)
headLineBodyWidth.isActive = true headLineBodyWidth.isActive = true
headlineBody.widthAnchor.constraint(lessThanOrEqualToConstant: maxWidth).isActive = true
//Caret view //Caret view
caretButton.translatesAutoresizingMaskIntoConstraints = false caretButton.translatesAutoresizingMaskIntoConstraints = false
caretButton.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true caretButton.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
container.bottomAnchor.constraint(equalTo: caretButton.bottomAnchor, constant: 0).isActive = true container.bottomAnchor.constraint(equalTo: caretButton.bottomAnchor, constant: 0).isActive = true
caretButton.topAnchor.constraint(greaterThanOrEqualTo: headlineBody.bottomAnchor, constant: spaceBetweenConstant).isActive = true caretButton.topAnchor.constraint(greaterThanOrEqualTo: headlineBody.bottomAnchor, constant: PaddingTwo).isActive = true
//Background image view //Background image view
backgroundImageView.translatesAutoresizingMaskIntoConstraints = false backgroundImageView.translatesAutoresizingMaskIntoConstraints = false
@ -67,13 +66,6 @@ import Foundation
} }
// MARK: - MVMCoreUIMoleculeViewProtocol // MARK: - MVMCoreUIMoleculeViewProtocol
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
backgroundImageView.setWithJSON(json?.optionalDictionaryForKey("image"), delegateObject: delegateObject, additionalData: additionalData)
headlineBody.setWithJSON(json?.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData)
caretButton.setWithJSON(json?.optionalDictionaryForKey("caretLink"), delegateObject: delegateObject, additionalData: additionalData)
}
open override func reset() { open override func reset() {
super.reset() super.reset()
headlineBody.reset() headlineBody.reset()

View File

@ -33,8 +33,9 @@ open class Stack<T>: Container where T: StackModelProtocol {
}) })
// Adds the views // Adds the views
let totalSpace = getTotalSpace()
for (index, view) in stackItems.enumerated() { for (index, view) in stackItems.enumerated() {
addView(view, stackModel.molecules[index], percentModifier: getPercentModifier(), lastItem: lastItemIndex == index) addView(view, stackModel.molecules[index], totalSpacing: totalSpace, lastItem: lastItemIndex == index)
} }
} }
@ -173,14 +174,12 @@ open class Stack<T>: Container where T: StackModelProtocol {
// MARK: - Adding to stack // MARK: - Adding to stack
/// Gets the percent modifier. This value is used to help properly calculate percent for stack items when spacing is involved. /// Gets the percent modifier. This value is used to help properly calculate percent for stack items when spacing is involved.
private func getPercentModifier() -> CGFloat { private func getTotalSpace() -> CGFloat {
guard let stackModel = stackModel else { return 0.0 } guard let stackModel = stackModel else { return 0.0 }
var totalSpace: CGFloat = 0.0 var totalSpace: CGFloat = 0.0
var totalViews = 0
var firstMoleculeFound = false var firstMoleculeFound = false
for stackItemModel in stackModel.molecules { for stackItemModel in stackModel.molecules {
guard !stackItemModel.gone else { continue } guard !stackItemModel.gone else { continue }
totalViews += 1
let spacing = stackItemModel.spacing ?? stackModel.spacing let spacing = stackItemModel.spacing ?? stackModel.spacing
if firstMoleculeFound { if firstMoleculeFound {
totalSpace += spacing totalSpace += spacing
@ -189,11 +188,11 @@ open class Stack<T>: Container where T: StackModelProtocol {
totalSpace += (stackModel.useStackSpacingBeforeFirstItem ? spacing : stackItemModel.spacing ?? 0) totalSpace += (stackModel.useStackSpacingBeforeFirstItem ? spacing : stackItemModel.spacing ?? 0)
} }
} }
return (totalViews > 0 ? -(totalSpace / CGFloat(totalViews)) : 0) return totalSpace
} }
/// Adds the stack item view /// Adds the stack item view
private func addView(_ view: UIView,_ model: StackItemModelProtocol, percentModifier: CGFloat, lastItem: Bool) { private func addView(_ view: UIView,_ model: StackItemModelProtocol, totalSpacing: CGFloat, lastItem: Bool) {
guard let stackModel = self.stackModel else { return } guard let stackModel = self.stackModel else { return }
guard !model.gone else { guard !model.gone else {
// Gone views do not show // Gone views do not show
@ -223,7 +222,9 @@ open class Stack<T>: Container where T: StackModelProtocol {
pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0)
pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0)
if let percent = model.percent { if let percent = model.percent {
view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: CGFloat(percent)/100.0, constant: percentModifier).isActive = true let multiplier = CGFloat(percent)/100.0
let constant = multiplier * totalSpacing
view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: multiplier, constant: -constant).isActive = true
} }
if lastItem { if lastItem {
pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
@ -240,7 +241,9 @@ open class Stack<T>: Container where T: StackModelProtocol {
pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0) pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0)
pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
if let percent = model.percent { if let percent = model.percent {
view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: CGFloat(percent)/100.0, constant: percentModifier).isActive = true let multiplier = CGFloat(percent)/100.0
let constant = multiplier * totalSpacing
view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: multiplier, constant: -constant).isActive = true
} }
if lastItem { if lastItem {
pinView(contentView, toView: view, attribute: .right, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .right, relation: .equal, priority: .required, constant: 0)

View File

@ -27,10 +27,10 @@ import Foundation
ModelRegistry.register(LabelAttributeActionModel.self) ModelRegistry.register(LabelAttributeActionModel.self)
// Buttons // Buttons
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: PrimaryButton.self, viewModelClass: ButtonModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TwoButtonView.self, viewModelClass: TwoButtonViewModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TwoButtonView.self, viewModelClass: TwoButtonViewModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Link.self, viewModelClass: LinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Link.self, viewModelClass: LinkModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretButton.self, viewModelClass: CaretLinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretLink.self, viewModelClass: CaretLinkModel.self)
// Entry Field // Entry Field
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TextEntryField.self, viewModelClass: TextEntryFieldModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TextEntryField.self, viewModelClass: TextEntryFieldModel.self)

View File

@ -30,14 +30,14 @@ import Foundation
case screenHeading case screenHeading
case header case header
case footer case footer
case moleculeStack case stack
case isAtomicTabs case isAtomicTabs
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
pageType = try typeContainer.decode(String.self, forKey: .pageType) pageType = try typeContainer.decode(String.self, forKey: .pageType)
moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .moleculeStack) moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .stack)
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading) screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs)
header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header) header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header)
@ -47,7 +47,7 @@ import Foundation
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(pageType, forKey: .pageType) try container.encode(pageType, forKey: .pageType)
try container.encode(moleculeStack, forKey: .moleculeStack) try container.encode(moleculeStack, forKey: .stack)
try container.encodeIfPresent(screenHeading, forKey: .screenHeading) try container.encodeIfPresent(screenHeading, forKey: .screenHeading)
try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs) try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs)
try container.encodeModelIfPresent(header, forKey: .header) try container.encodeModelIfPresent(header, forKey: .header)

View File

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