merge from develop
This commit is contained in:
commit
d02586f613
@ -111,6 +111,10 @@
|
||||
9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; };
|
||||
946EE1BA237B66D80036751F /* MoleculeModelHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946EE1B9237B66D80036751F /* MoleculeModelHelper.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 */; };
|
||||
94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.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 */; };
|
||||
94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.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, ); }; };
|
||||
94FB966323D797DA003D482B /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94FB966123D797DA003D482B /* MFTextButton.m */; };
|
||||
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 */; };
|
||||
D2E2A99C23D8D975000B42E6 /* ImageHeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99B23D8D975000B42E6 /* ImageHeadlineBodyModel.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 */; };
|
||||
D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */; };
|
||||
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; };
|
||||
DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.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 */; };
|
||||
DBEFFA04225A829700230692 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB891E822253FA8500022516 /* Label.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
@ -425,6 +434,10 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -432,6 +445,8 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -643,6 +658,9 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -650,7 +668,7 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -678,6 +696,7 @@
|
||||
012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */,
|
||||
D28A837823C7D5BC00DFE4FC /* PageModelProtocol.swift */,
|
||||
011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */,
|
||||
D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */,
|
||||
);
|
||||
path = ModelProtocols;
|
||||
sourceTree = "<group>";
|
||||
@ -845,6 +864,13 @@
|
||||
D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */,
|
||||
D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */,
|
||||
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;
|
||||
sourceTree = "<group>";
|
||||
@ -1171,13 +1197,13 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
01F2A03123A4498200D954D8 /* CaretLinkModel.swift */,
|
||||
DBC4391A224421A0001AB423 /* CaretButton.swift */,
|
||||
DBC4391A224421A0001AB423 /* CaretLink.swift */,
|
||||
D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */,
|
||||
D282AACA2243C61700C46919 /* ButtonView.swift */,
|
||||
D2E2A99E23E07F8A000B42E6 /* PillButton.swift */,
|
||||
D28A838823CCCFCB00DFE4FC /* LinkModel.swift */,
|
||||
C07065C32395677300FBF997 /* Link.swift */,
|
||||
D28A838C23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift */,
|
||||
D28A837623C79FC600DFE4FC /* MFCustomButton+ActionModel.swift */,
|
||||
C07065C32395677300FBF997 /* Link.swift */,
|
||||
);
|
||||
path = Buttons;
|
||||
sourceTree = "<group>";
|
||||
@ -1376,6 +1402,7 @@
|
||||
D2B18B7D236090D500A9AEDC /* BaseClasses */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */,
|
||||
C003506023AA94CD00B6AC29 /* Button.swift */,
|
||||
D2B18B7E2360913400A9AEDC /* Control.swift */,
|
||||
D2B18B802360945C00A9AEDC /* View.swift */,
|
||||
@ -1424,6 +1451,7 @@
|
||||
D29DF27521E79E81003B2FB9 /* MVMCoreUILoggingHandler.h in Headers */,
|
||||
D29DF28B21E7AC2B003B2FB9 /* ViewConstrainingView.h in Headers */,
|
||||
D29DF2B321E7B76D003B2FB9 /* MFLoadingSpinner.h in Headers */,
|
||||
94AF4A3E23E9D13900676048 /* MFCaretButton.h in Headers */,
|
||||
0A21DB8A235E06EF00C160A2 /* MFDigitTextBox.h in Headers */,
|
||||
D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */,
|
||||
0A21DB8C235E06EF00C160A2 /* MFDigitTextField.h in Headers */,
|
||||
@ -1442,6 +1470,7 @@
|
||||
D29DF2CA21E7BFC8003B2FB9 /* MFSizeThreshold.h in Headers */,
|
||||
D29DF28021E7AA51003B2FB9 /* MVMCoreUIDetailViewProtocol.h in Headers */,
|
||||
D29DF2BD21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h in Headers */,
|
||||
94AF4A4223E9D19E00676048 /* MFCaretView.h in Headers */,
|
||||
D29DF2EE21ECEADF003B2FB9 /* MFFonts.h in Headers */,
|
||||
D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */,
|
||||
D29770F321F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h in Headers */,
|
||||
@ -1454,6 +1483,7 @@
|
||||
D29DF2A121E7AF4E003B2FB9 /* MVMCoreUIUtility.h in Headers */,
|
||||
D29DF17621E69E1F003B2FB9 /* PrimaryButton.h in Headers */,
|
||||
D29DF2C821E7BFC1003B2FB9 /* MFSizeObject.h in Headers */,
|
||||
94F217B623E0BF6100A47C06 /* PrimaryButtonView.h in Headers */,
|
||||
D29DF32021ED0CBA003B2FB9 /* LabelView.h in Headers */,
|
||||
D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */,
|
||||
D29DF2E121E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h in Headers */,
|
||||
@ -1590,6 +1620,7 @@
|
||||
D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */,
|
||||
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */,
|
||||
0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */,
|
||||
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */,
|
||||
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
|
||||
D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */,
|
||||
D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */,
|
||||
@ -1605,6 +1636,7 @@
|
||||
014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */,
|
||||
D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */,
|
||||
012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */,
|
||||
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */,
|
||||
94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */,
|
||||
D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */,
|
||||
014AA73123C5059B006F3E93 /* ListPageTemplateModel.swift in Sources */,
|
||||
@ -1639,6 +1671,7 @@
|
||||
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
|
||||
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */,
|
||||
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */,
|
||||
94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */,
|
||||
0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */,
|
||||
0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */,
|
||||
D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */,
|
||||
@ -1685,6 +1718,7 @@
|
||||
944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */,
|
||||
D2E2A99623D8CF85000B42E6 /* HeadlineBodyLinkToggleModel.swift in Sources */,
|
||||
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
|
||||
94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */,
|
||||
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
|
||||
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
|
||||
D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */,
|
||||
@ -1735,10 +1769,12 @@
|
||||
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */,
|
||||
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
|
||||
0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */,
|
||||
94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */,
|
||||
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */,
|
||||
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
|
||||
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */,
|
||||
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
|
||||
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */,
|
||||
D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */,
|
||||
94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */,
|
||||
D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */,
|
||||
@ -1749,7 +1785,7 @@
|
||||
D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */,
|
||||
C003506123AA94CD00B6AC29 /* Button.swift in Sources */,
|
||||
0A14F6A523E4803A00EDF7F7 /* StackView.swift in Sources */,
|
||||
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */,
|
||||
DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */,
|
||||
0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */,
|
||||
0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */,
|
||||
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */,
|
||||
|
||||
@ -18,14 +18,21 @@ public enum ButtonSize: String, Codable {
|
||||
case tiny
|
||||
}
|
||||
|
||||
public class ButtonModel: MoleculeModelProtocol {
|
||||
public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
public static var identifier: String = "button"
|
||||
public var moleculeName: String?
|
||||
public var backgroundColor: Color?
|
||||
public var title: String
|
||||
public var action: ActionModelProtocol
|
||||
public var enabled: Bool = true
|
||||
public var style: ButtonStyle?
|
||||
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 requiredGroups: [String]?
|
||||
|
||||
@ -34,13 +41,26 @@ public class ButtonModel: MoleculeModelProtocol {
|
||||
self.action = action
|
||||
}
|
||||
|
||||
init(secondaryButtonWith title: String, action: ActionModelProtocol) {
|
||||
self.title = title
|
||||
self.action = action
|
||||
style = .secondary
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case title
|
||||
case action
|
||||
case enabled
|
||||
case style
|
||||
case size
|
||||
case fillColor
|
||||
case textColor
|
||||
case borderColor
|
||||
case disabledFillColor
|
||||
case disabledTextColor
|
||||
case disabledBorderColor
|
||||
case required
|
||||
case requiredGroups
|
||||
}
|
||||
@ -60,6 +80,15 @@ public class ButtonModel: MoleculeModelProtocol {
|
||||
if let size = try typeContainer.decodeIfPresent(ButtonSize.self, forKey: .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 {
|
||||
@ -68,8 +97,16 @@ public class ButtonModel: MoleculeModelProtocol {
|
||||
try container.encode(title, forKey: .title)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encodeIfPresent(style, forKey: .style)
|
||||
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(requiredGroups, forKey: .requiredGroups)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// CaretButton.swift
|
||||
// CaretLink.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// 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
|
||||
@ -49,7 +49,9 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
|
||||
didSet { changeCaretColor() }
|
||||
}
|
||||
|
||||
public func updateView(_ size: CGFloat) { }
|
||||
public override func updateView(_ size: CGFloat) {
|
||||
titleLabel?.font = MFStyler.fontB1()
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Methods
|
||||
@ -61,10 +63,18 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
|
||||
setTitleColor(disabledColor, for: .disabled)
|
||||
|
||||
if let rightCaretView = rightView as? CaretView {
|
||||
rightCaretView.enabledColor = enabledColor
|
||||
rightCaretView.disabledColor = disabledColor
|
||||
rightCaretView.isEnabled = isEnabled
|
||||
}
|
||||
}
|
||||
|
||||
private func createCaretView() -> CaretView {
|
||||
let caret = CaretView()
|
||||
caret.lineWidth = 1.5
|
||||
return caret
|
||||
}
|
||||
|
||||
private func addCaretImageView() {
|
||||
|
||||
rightView?.removeFromSuperview()
|
||||
@ -75,7 +85,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
|
||||
let edgeInsets: UIEdgeInsets = contentEdgeInsets
|
||||
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?.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(caretView)
|
||||
@ -115,33 +125,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
|
||||
setTitleColor(disabledColor, for: .disabled)
|
||||
}
|
||||
|
||||
@objc public func setWithJSON(_ json: [AnyHashable: Any]?, 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]?) {
|
||||
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let caretLinkModel = model as? CaretLinkModel else { return }
|
||||
if let color = caretLinkModel.backgroundColor {
|
||||
backgroundColor = color.uiColor
|
||||
@ -163,7 +147,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI
|
||||
return .leading
|
||||
}
|
||||
|
||||
public class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 10
|
||||
open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return 10.5
|
||||
}
|
||||
}
|
||||
@ -9,14 +9,14 @@
|
||||
import Foundation
|
||||
import MVMCore
|
||||
|
||||
public class CaretLinkModel: MoleculeModelProtocol {
|
||||
public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
public static var identifier: String = "caretLink"
|
||||
public var backgroundColor: Color?
|
||||
public var title: String
|
||||
public var action: ActionModelProtocol
|
||||
public var enabledColor: Color = Color(uiColor: .black)
|
||||
public var disabledColor: Color? = Color(uiColor: .mfSilver())
|
||||
public var enabled: Bool = true
|
||||
public var enabled = true
|
||||
|
||||
public init(title: String, action: ActionModelProtocol) {
|
||||
self.title = title
|
||||
|
||||
@ -46,7 +46,7 @@ import UIKit
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public class LinkModel: MoleculeModelProtocol {
|
||||
public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
public static var identifier: String = "link"
|
||||
public var backgroundColor: Color?
|
||||
public var title: String
|
||||
|
||||
179
MVMCoreUI/Atoms/Buttons/PillButton.swift
Normal file
179
MVMCoreUI/Atoms/Buttons/PillButton.swift
Normal 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
|
||||
}
|
||||
}
|
||||
@ -21,7 +21,7 @@ import UIKit
|
||||
let caret = CaretView()
|
||||
caret.direction = .down
|
||||
caret.lineWidth = 1.5
|
||||
caret.isUserInteractionEnabled = true
|
||||
caret.isUserInteractionEnabled = false
|
||||
caret.heightAnchor.constraint(equalToConstant: 9).isActive = true
|
||||
caret.widthAnchor.constraint(equalToConstant: 16).isActive = true
|
||||
return caret
|
||||
|
||||
@ -25,7 +25,7 @@ import UIKit
|
||||
//--------------------------------------------------
|
||||
|
||||
open private(set) var textField: TextField = {
|
||||
let textField = TextField(frame: .zero)
|
||||
let textField = TextField()
|
||||
textField.isAccessibilityElement = true
|
||||
textField.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
textField.font = MFStyler.fontForTextField()
|
||||
@ -58,7 +58,7 @@ import UIKit
|
||||
get { return super.isEnabled }
|
||||
set (enabled) {
|
||||
super.isEnabled = enabled
|
||||
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
@ -99,7 +99,7 @@ import UIKit
|
||||
//--------------------------------------------------
|
||||
|
||||
public var validationBlock: ((_ value: String?) -> Bool)?
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate Properties
|
||||
//--------------------------------------------------
|
||||
@ -169,6 +169,9 @@ import UIKit
|
||||
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16)
|
||||
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))
|
||||
entryFieldContainer.addGestureRecognizer(tap)
|
||||
|
||||
@ -225,7 +228,7 @@ import UIKit
|
||||
/// Validates the text of the entry field.
|
||||
@discardableResult
|
||||
@objc public func validateTextField() -> Bool {
|
||||
|
||||
|
||||
isValid = validationBlock?(text) ?? true
|
||||
|
||||
if isValid {
|
||||
@ -277,7 +280,7 @@ import UIKit
|
||||
guard let model = model as? TextEntryFieldModel else { return }
|
||||
|
||||
FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol)
|
||||
|
||||
|
||||
textColor.enabled = model.enabledTextColor?.uiColor
|
||||
textColor.disabled = model.disabledTextColor?.uiColor
|
||||
text = model.text
|
||||
|
||||
@ -31,7 +31,7 @@ import UIKit
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(view)
|
||||
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
|
||||
previous = view
|
||||
NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false)
|
||||
|
||||
@ -91,6 +91,10 @@ public typealias ButtonAction = (Button) -> ()
|
||||
if let backgroundColor = model?.backgroundColor {
|
||||
self.backgroundColor = backgroundColor.uiColor
|
||||
}
|
||||
|
||||
guard let model = model as? ButtonModelProtocol else { return }
|
||||
isEnabled = model.enabled
|
||||
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
|
||||
14
MVMCoreUI/BaseClasses/ButtonModelProtocol.swift
Normal file
14
MVMCoreUI/BaseClasses/ButtonModelProtocol.swift
Normal 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 }
|
||||
}
|
||||
@ -6,11 +6,11 @@
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
import UIKit
|
||||
|
||||
public typealias ColorHexTuple = (uiColor: UIColor, hex: String)
|
||||
|
||||
|
||||
extension UIColor {
|
||||
|
||||
/// Dictionary to access brand approved colors by name.
|
||||
@ -25,6 +25,7 @@ extension UIColor {
|
||||
"coolGray1": (.mvmCoolGray1, "#F6F6F6"),
|
||||
"coolGray3": (.mvmCoolGray3, "#D8DADA"),
|
||||
"coolGray6": (.mvmCoolGray6, "#747676"),
|
||||
"coolGray10": (.mvmCoolGray10, "#333333"),
|
||||
"vzupGold": (.vzupGold, "#B89B56"),
|
||||
"vzupYellow1": (.vzupYellow1, "#F9D542"),
|
||||
"vzupYellow2": (.vzupYellow2, "#F4CA53"),
|
||||
@ -67,6 +68,9 @@ extension UIColor {
|
||||
/// HEX: #747676
|
||||
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
|
||||
//--------------------------------------------------
|
||||
@ -196,15 +200,4 @@ extension UIColor {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
public class func getColorAndHexFromName(_ name: String) -> ColorHexTuple? {
|
||||
|
||||
for row in names {
|
||||
if name == row.key {
|
||||
return row.value
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ public final class Color: Codable {
|
||||
}
|
||||
|
||||
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.hex = colorTuple.hex
|
||||
determineRGBA()
|
||||
@ -73,7 +73,7 @@ public final class Color: Codable {
|
||||
if colorString.hasPrefix("#") {
|
||||
hex = colorString.replacingOccurrences(of: "#", with: "")
|
||||
} 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: "")
|
||||
name = colorString
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "TopLabelsAndBottomButtonsTableViewController.h"
|
||||
#import <MVMCoreUI/PrimaryButtonView.h>
|
||||
#import <MVMCoreUI/MVMCoreUIUtility.h>
|
||||
#import <MVMCoreUI/StackableViewController.h>
|
||||
#import <MVMCoreUI/MVMCoreUICommonViewsUtility.h>
|
||||
@ -121,7 +122,7 @@
|
||||
// Sets up the buttons/button.
|
||||
NSDictionary *primaryButtonDictionary = [self primaryButtonMap];
|
||||
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.primaryButton = buttonView.primaryButton;
|
||||
|
||||
@ -439,16 +440,16 @@
|
||||
|
||||
|
||||
- (void)setPrimaryLeftButtonHidden:(BOOL)left rightButtonHidden:(BOOL)right {
|
||||
if ([self.bottomView isKindOfClass:[TwoButtonView class]]) {
|
||||
TwoButtonView *buttonView = (TwoButtonView *)self.bottomView;
|
||||
if ([self.bottomView isKindOfClass:[PrimaryButtonView class]]) {
|
||||
PrimaryButtonView *buttonView = (PrimaryButtonView *)self.bottomView;
|
||||
if (right && !left) {
|
||||
[buttonView hideRightButton];
|
||||
[buttonView hidePrimaryRightButton];
|
||||
} else if (!right && left) {
|
||||
[buttonView hideLeftButton];
|
||||
[buttonView hidePrimaryLeftButton];
|
||||
} else if (right && left) {
|
||||
[buttonView hideBothButtons];
|
||||
[buttonView hideBothPrimaryButtons];
|
||||
} else if (!right && !left) {
|
||||
[buttonView showBothButtons];
|
||||
[buttonView showBothPrimaryButtons];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "TopLabelsAndBottomButtonsViewController.h"
|
||||
#import <MVMCoreUI/PrimaryButtonView.h>
|
||||
#import <MVMCoreUI/MFSizeObject.h>
|
||||
#import <MVMCoreUI/MVMCoreUICommonViewsUtility.h>
|
||||
#import <MVMCoreUI/UIColor+MFConvenience.h>
|
||||
@ -81,18 +82,18 @@
|
||||
}
|
||||
|
||||
if (!self.customBottemView) {
|
||||
TwoButtonView *buttonView = (TwoButtonView *)self.bottomView;
|
||||
PrimaryButtonView *buttonView = (PrimaryButtonView *)self.bottomView;
|
||||
if (self.secondaryButton || self.primaryButton) {
|
||||
UIEdgeInsets paddingForBottomButtons = [self paddingForBottomButtons];
|
||||
[buttonView setLeftPinConstant:paddingForBottomButtons.left];
|
||||
[buttonView setRightPinConstant:paddingForBottomButtons.right];
|
||||
buttonView.leftPin.constant = paddingForBottomButtons.left;
|
||||
buttonView.rightPin.constant = paddingForBottomButtons.right;
|
||||
buttonView.topPin.constant = paddingForBottomButtons.top;
|
||||
buttonView.bottomPin.constant = paddingForBottomButtons.bottom;
|
||||
} else {
|
||||
buttonView.topPin.constant = 0;
|
||||
buttonView.bottomPin.constant = 0;
|
||||
[buttonView setLeftPinConstant:0];
|
||||
[buttonView setRightPinConstant:0];
|
||||
buttonView.leftPin.constant = 0;
|
||||
buttonView.rightPin.constant = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +139,7 @@
|
||||
// Sets up the buttons/button.
|
||||
NSDictionary *primaryButtonDictionary = [self primaryButtonMap];
|
||||
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.primaryButton = buttonView.primaryButton;
|
||||
bottomView = buttonView;
|
||||
|
||||
26
MVMCoreUI/Legacy/Views/MFCaretButton.h
Normal file
26
MVMCoreUI/Legacy/Views/MFCaretButton.h
Normal 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
|
||||
113
MVMCoreUI/Legacy/Views/MFCaretButton.m
Normal file
113
MVMCoreUI/Legacy/Views/MFCaretButton.m
Normal 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
|
||||
16
MVMCoreUI/Legacy/Views/MFCaretView.h
Normal file
16
MVMCoreUI/Legacy/Views/MFCaretView.h
Normal 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
|
||||
|
||||
93
MVMCoreUI/Legacy/Views/MFCaretView.m
Normal file
93
MVMCoreUI/Legacy/Views/MFCaretView.m
Normal 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
|
||||
63
MVMCoreUI/Legacy/Views/PrimaryButtonView.h
Normal file
63
MVMCoreUI/Legacy/Views/PrimaryButtonView.h
Normal 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
|
||||
392
MVMCoreUI/Legacy/Views/PrimaryButtonView.m
Normal file
392
MVMCoreUI/Legacy/Views/PrimaryButtonView.m
Normal 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
|
||||
@ -81,6 +81,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[];
|
||||
#import <MVMCoreUI/MVMCoreUICheckBox.h>
|
||||
#import <MVMCoreUI/MVMCoreUISwitch.h>
|
||||
#import <MVMCoreUI/MFRadioButton.h>
|
||||
#import <MVMCoreUI/MFCaretView.h>
|
||||
|
||||
#pragma mark Buttons
|
||||
#import <MVMCoreUI/MFButtonProtocol.h>
|
||||
@ -88,6 +89,8 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[];
|
||||
#import <MVMCoreUI/MFCustomButton.h>
|
||||
#import <MVMCoreUI/PrimaryButton.h>
|
||||
#import <MVMCoreUI/MFTextButton.h>
|
||||
#import <MVMCoreUI/PrimaryButtonView.h>
|
||||
#import <MVMCoreUI/MFCaretButton.h>
|
||||
|
||||
#pragma mark TextFields
|
||||
#import <MVMCoreUI/MFTextField.h>
|
||||
|
||||
@ -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 }
|
||||
}
|
||||
@ -8,12 +8,12 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class TwoButtonView: ViewConstrainingView {
|
||||
open var primaryButton: PrimaryButton? = PrimaryButton.button()
|
||||
open var secondaryButton: PrimaryButton? = PrimaryButton.button()
|
||||
open var viewForButtons: UIView?
|
||||
public var heightConstraint: NSLayoutConstraint?
|
||||
|
||||
@objcMembers open class TwoButtonView: View, MVMCoreUIViewConstrainingProtocol {
|
||||
open var primaryButton: PillButton = PillButton()
|
||||
open var secondaryButton: PillButton = PillButton()
|
||||
private var stack = UIStackView()
|
||||
private var equalWidthConstraint: NSLayoutConstraint?
|
||||
|
||||
public init() {
|
||||
super.init(frame: .zero)
|
||||
}
|
||||
@ -26,289 +26,100 @@ import UIKit
|
||||
super.init(frame: frame)
|
||||
}
|
||||
|
||||
public func setDefaultCustom() {
|
||||
primaryButton?.setAsStandardCustom()
|
||||
secondaryButton?.setAsSecondaryCustom()
|
||||
public func setDefault() {
|
||||
primaryButton.stylePrimary()
|
||||
secondaryButton.styleSecondary()
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
self.primaryButton?.updateView(size)
|
||||
self.secondaryButton?.updateView(size)
|
||||
})
|
||||
self.primaryButton.updateView(size)
|
||||
self.secondaryButton.updateView(size)
|
||||
}
|
||||
|
||||
open override func 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
|
||||
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() {
|
||||
super.reset()
|
||||
primaryButton?.setAsStandardCustom()
|
||||
secondaryButton?.setAsSecondaryCustom()
|
||||
setDefault()
|
||||
}
|
||||
|
||||
// MARK: - Constraining
|
||||
func createPrimaryButton() {
|
||||
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 {
|
||||
|
||||
// MARK: - MVMCoreUIViewConstrainingProtocol
|
||||
open func horizontalAlignment() -> UIStackView.Alignment {
|
||||
return .center
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Deprecate
|
||||
extension TwoButtonView {
|
||||
@available(*, deprecated)
|
||||
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 {
|
||||
primaryButton?.setWithActionMap(primaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
|
||||
secondaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
|
||||
} else if primaryButtonMap != nil {
|
||||
primaryButton?.setWithActionMap(primaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
|
||||
primaryButton?.bordered = false
|
||||
} else if secondaryButtonMap != nil {
|
||||
secondaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
|
||||
secondaryButton?.bordered = true
|
||||
|
||||
// MARK: - ModelMoleculeViewProtocol
|
||||
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
guard let model = molecule as? TwoButtonViewModel else { return 0 }
|
||||
return PillButton.estimatedHeight(forRow: model.primaryButton ?? model.secondaryButton, delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.setWithModel(model, delegateObject, additionalData)
|
||||
guard let model = model as? TwoButtonViewModel else { return }
|
||||
if let secondaryModel = model.secondaryButton {
|
||||
showSecondaryButton()
|
||||
secondaryButton.setWithModel(secondaryModel, delegateObject, additionalData)
|
||||
} else {
|
||||
hideSecondaryButton()
|
||||
}
|
||||
if let primaryModel = model.primaryButton {
|
||||
showPrimaryButton()
|
||||
primaryButton.setWithModel(primaryModel, delegateObject, additionalData)
|
||||
} else {
|
||||
hidePrimaryButton()
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated)
|
||||
open func setup(withButtonMap buttonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) {
|
||||
let secondaryButtonMap = buttonMap?.optionalDictionaryForKey(KeySecondaryButton)
|
||||
let primaryButtonMap = buttonMap?.optionalDictionaryForKey(KeyPrimaryButton)
|
||||
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
|
||||
}
|
||||
|
||||
@available(*, deprecated)
|
||||
public convenience init(buttonSmall small: Bool, buttonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: AnyHashable]?, buttonDelegate: Any?) {
|
||||
self.init()
|
||||
setup(withButtonMap: buttonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
|
||||
primaryButton?.setAsSmall(small)
|
||||
secondaryButton?.setAsSmall(small)
|
||||
}
|
||||
|
||||
@available(*, deprecated)
|
||||
public convenience init(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) {
|
||||
self.init()
|
||||
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
|
||||
}
|
||||
}
|
||||
|
||||
extension TwoButtonView: ModelMoleculeViewProtocol {
|
||||
public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let model = model as? TwoButtonViewModel else { return }
|
||||
setupUI(primaryButtonShowing: model.primaryButton != nil, secondaryButtonShowing: model.secondaryButton != nil)
|
||||
setDefaultCustom()
|
||||
primaryButton?.setWithModel(model.primaryButton, delegateObject, additionalData)
|
||||
secondaryButton?.setWithModel(model.secondaryButton, delegateObject, additionalData)
|
||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,9 +8,35 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public struct TwoButtonViewModel: MoleculeModelProtocol {
|
||||
public class TwoButtonViewModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "twoButtonView"
|
||||
public var backgroundColor: Color?
|
||||
public var primaryButton: 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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ import UIKit
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,10 +171,8 @@ import UIKit
|
||||
guard let model = model as? CornerLabelsModel else { return }
|
||||
if middleView != nil {
|
||||
(middleView as? ModelMoleculeViewProtocol)?.setWithModel(model, delegateObject, additionalData)
|
||||
} else {
|
||||
if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model.molecule, delegateObject) {
|
||||
addMiddleView(molecule)
|
||||
}
|
||||
} else if let moleculeModel = model.molecule, let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(moleculeModel, delegateObject) {
|
||||
addMiddleView(molecule)
|
||||
}
|
||||
|
||||
topLeftLabel.setWithModel(model.topLeftLabel, delegateObject, additionalData)
|
||||
|
||||
@ -15,9 +15,9 @@ public class CornerLabelsModel: MoleculeModelProtocol {
|
||||
public var topRightLabel: LabelModel?
|
||||
public var bottomLeftLabel: LabelModel?
|
||||
public var bottomRightLabel: LabelModel?
|
||||
public var molecule: MoleculeModelProtocol
|
||||
public var molecule: MoleculeModelProtocol?
|
||||
|
||||
init(with molecule: MoleculeModelProtocol) {
|
||||
init(with molecule: MoleculeModelProtocol?) {
|
||||
self.molecule = molecule
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ public class CornerLabelsModel: MoleculeModelProtocol {
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
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)
|
||||
topRightLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .topRightLabel)
|
||||
bottomLeftLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .bottomLeftLabel)
|
||||
|
||||
@ -9,9 +9,8 @@
|
||||
import Foundation
|
||||
@objcMembers public class HeadLineBodyCaretLinkImage: Container {
|
||||
let headlineBody = HeadlineBody(frame: .zero)
|
||||
let caretButton = CaretButton(frame: .zero)
|
||||
let caretButton = CaretLink(frame: .zero)
|
||||
let backgroundImageView = MFLoadImageView(pinnedEdges: .all)
|
||||
var spaceBetweenConstant: CGFloat = 104.0
|
||||
let maxWidth: CGFloat = 350.0
|
||||
static let heightConstant: CGFloat = 320.0
|
||||
var heightConstraint: NSLayoutConstraint?
|
||||
@ -44,17 +43,17 @@ import Foundation
|
||||
headlineBody.leadingAnchor.constraint(equalTo: container.leadingAnchor, 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)
|
||||
headLineBodyWidth.priority = .defaultHigh
|
||||
headlineBody.widthAnchor.constraint(equalTo: container.widthAnchor, multiplier: 0.67).isActive = true
|
||||
let headLineBodyWidth = headlineBody.widthAnchor.constraint(lessThanOrEqualToConstant: maxWidth)
|
||||
headLineBodyWidth.priority = UILayoutPriority(250)
|
||||
headLineBodyWidth.isActive = true
|
||||
headlineBody.widthAnchor.constraint(lessThanOrEqualToConstant: maxWidth).isActive = true
|
||||
|
||||
//Caret view
|
||||
caretButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
caretButton.leadingAnchor.constraint(equalTo: container.leadingAnchor, 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
|
||||
backgroundImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
@ -67,13 +66,6 @@ import Foundation
|
||||
}
|
||||
|
||||
// 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() {
|
||||
super.reset()
|
||||
headlineBody.reset()
|
||||
|
||||
@ -33,8 +33,9 @@ open class Stack<T>: Container where T: StackModelProtocol {
|
||||
})
|
||||
|
||||
// Adds the views
|
||||
let totalSpace = getTotalSpace()
|
||||
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
|
||||
/// 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 }
|
||||
var totalSpace: CGFloat = 0.0
|
||||
var totalViews = 0
|
||||
var firstMoleculeFound = false
|
||||
for stackItemModel in stackModel.molecules {
|
||||
guard !stackItemModel.gone else { continue }
|
||||
totalViews += 1
|
||||
let spacing = stackItemModel.spacing ?? stackModel.spacing
|
||||
if firstMoleculeFound {
|
||||
totalSpace += spacing
|
||||
@ -189,11 +188,11 @@ open class Stack<T>: Container where T: StackModelProtocol {
|
||||
totalSpace += (stackModel.useStackSpacingBeforeFirstItem ? spacing : stackItemModel.spacing ?? 0)
|
||||
}
|
||||
}
|
||||
return (totalViews > 0 ? -(totalSpace / CGFloat(totalViews)) : 0)
|
||||
return totalSpace
|
||||
}
|
||||
|
||||
/// 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 !model.gone else {
|
||||
// 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(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0)
|
||||
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 {
|
||||
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(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
|
||||
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 {
|
||||
pinView(contentView, toView: view, attribute: .right, relation: .equal, priority: .required, constant: 0)
|
||||
|
||||
@ -27,10 +27,10 @@ import Foundation
|
||||
ModelRegistry.register(LabelAttributeActionModel.self)
|
||||
|
||||
// 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: 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
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TextEntryField.self, viewModelClass: TextEntryFieldModel.self)
|
||||
|
||||
@ -30,14 +30,14 @@ import Foundation
|
||||
case screenHeading
|
||||
case header
|
||||
case footer
|
||||
case moleculeStack
|
||||
case stack
|
||||
case isAtomicTabs
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
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)
|
||||
isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs)
|
||||
header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header)
|
||||
@ -47,7 +47,7 @@ import Foundation
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
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(isAtomicTabs, forKey: .isAtomicTabs)
|
||||
try container.encodeModelIfPresent(header, forKey: .header)
|
||||
|
||||
@ -41,7 +41,7 @@ import Foundation
|
||||
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
|
||||
isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs)
|
||||
header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header)
|
||||
header = try typeContainer.decodeMoleculeIfPresent(codingKey: .middle)
|
||||
middle = try typeContainer.decodeMoleculeIfPresent(codingKey: .middle)
|
||||
footer = try typeContainer.decodeMoleculeIfPresent(codingKey: .footer)
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user