Section List

This commit is contained in:
Pfeil, Scott Robert 2020-10-05 14:03:35 -04:00
parent 1bc655192a
commit 4862d3d07c
46 changed files with 650 additions and 114 deletions

View File

@ -305,6 +305,8 @@
D20C700B250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */; };
D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */; };
D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; };
D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2169300251E51E7002A6324 /* SectionListTemplate.swift */; };
D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2169302251E53D9002A6324 /* SectionListTemplateModel.swift */; };
D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */; };
D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */; };
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */; };
@ -464,6 +466,8 @@
D2CAC7CF2511052300C75681 /* CollapsableNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */; };
D2CAC7D12511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */; };
D2CAC7D3251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */; };
D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */; };
D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */; };
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; };
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; };
D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */; };
@ -481,6 +485,9 @@
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 */; };
D2EC7BD52527B7A600F540AF /* MoleculeSectionHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */; };
D2EC7BD92527B7CF00F540AF /* MoleculeSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */; };
D2EC7BDD2527B83700F540AF /* SectionHeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.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 */; };
@ -793,6 +800,8 @@
D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertView+Extension.swift"; sourceTree = "<group>"; };
D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModel.swift; sourceTree = "<group>"; };
D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
D2169300251E51E7002A6324 /* SectionListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionListTemplate.swift; sourceTree = "<group>"; };
D2169302251E53D9002A6324 /* SectionListTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionListTemplateModel.swift; sourceTree = "<group>"; };
D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = "<group>"; };
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = "<group>"; };
D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemModelProtocol.swift; sourceTree = "<group>"; };
@ -954,6 +963,8 @@
D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotificationModel.swift; sourceTree = "<group>"; };
D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertMainView+Extension.swift"; sourceTree = "<group>"; };
D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertExpandableView+Extension.swift"; sourceTree = "<group>"; };
D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionFooterModel.swift; sourceTree = "<group>"; };
D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionFooter.swift; sourceTree = "<group>"; };
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = "<group>"; };
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = "<group>"; };
D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderModel.swift; sourceTree = "<group>"; };
@ -970,6 +981,9 @@
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>"; };
D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionHeaderModel.swift; sourceTree = "<group>"; };
D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionHeader.swift; sourceTree = "<group>"; };
D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderFooterView.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>"; };
DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeftRightLabelView.swift; sourceTree = "<group>"; };
@ -1680,6 +1694,8 @@
D264FAA4243F66A500D98315 /* CollectionTemplateItemProtocol.swift */,
D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */,
D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */,
D2169302251E53D9002A6324 /* SectionListTemplateModel.swift */,
D2169300251E51E7002A6324 /* SectionListTemplate.swift */,
);
path = Templates;
sourceTree = "<group>";
@ -1707,6 +1723,7 @@
D29DF10E21E67A77003B2FB9 /* Molecules */ = {
isa = PBXGroup;
children = (
D2EC7BD22527A1E400F540AF /* HeadersAndFooters */,
D2CAC7C9251104CB00C75681 /* TopNotification */,
D2509ED42472EE0B001BFB9D /* NavigationBar */,
D253BB9A24587023002DE544 /* OtherContainers */,
@ -1715,12 +1732,6 @@
D224798F2316A99F003FCCF9 /* LeftRightViews */,
D224798E2316A995003FCCF9 /* HorizontalCombinationViews */,
D224798D2316A988003FCCF9 /* VerticalCombinationViews */,
01EB368C23609801006832FA /* HeaderModel.swift */,
D256E9922412880000360572 /* Header.swift */,
D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */,
D2A514662213885800345BFB /* MoleculeHeaderView.swift */,
012A88EB238F084D00FE3DA1 /* FooterModel.swift */,
D274CA322236A78900B01B62 /* FooterView.swift */,
D260105723CF9CC500764D80 /* Doughnut */,
);
path = Molecules;
@ -2022,6 +2033,7 @@
0A5D59C323AD488600EFD9E9 /* Protocols */,
0A7918F423F5E7EA00772FF4 /* ImageView.swift */,
D272F5F82473163100BD1A8F /* BarButtonItem.swift */,
D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */,
);
path = BaseClasses;
sourceTree = "<group>";
@ -2085,6 +2097,23 @@
path = TopNotification;
sourceTree = "<group>";
};
D2EC7BD22527A1E400F540AF /* HeadersAndFooters */ = {
isa = PBXGroup;
children = (
01EB368C23609801006832FA /* HeaderModel.swift */,
D256E9922412880000360572 /* Header.swift */,
D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */,
D2A514662213885800345BFB /* MoleculeHeaderView.swift */,
012A88EB238F084D00FE3DA1 /* FooterModel.swift */,
D274CA322236A78900B01B62 /* FooterView.swift */,
D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */,
D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */,
D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */,
D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */,
);
path = HeadersAndFooters;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@ -2238,6 +2267,7 @@
D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */,
D28BA7452481652D00B75CB8 /* TabBarProtocol.swift in Sources */,
AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */,
D2EC7BD92527B7CF00F540AF /* MoleculeSectionHeader.swift in Sources */,
D28764AA2458980300CB882D /* ThreeLayerFillMiddleTemplate.swift in Sources */,
0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */,
D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */,
@ -2253,6 +2283,7 @@
AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */,
AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */,
D272F5F92473163100BD1A8F /* BarButtonItem.swift in Sources */,
D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */,
0A9D09202433796500D2E6C0 /* BarsIndicatorView.swift in Sources */,
D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */,
01004F3022721C3800991ECC /* RadioButton.swift in Sources */,
@ -2406,6 +2437,7 @@
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */,
014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */,
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */,
D2EC7BD52527B7A600F540AF /* MoleculeSectionHeaderModel.swift in Sources */,
AAA905DF24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift in Sources */,
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */,
@ -2418,6 +2450,7 @@
D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */,
0A775F2824893937009EFB58 /* ThreeHeadlineBodyLinkModel.swift in Sources */,
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */,
D2EC7BDD2527B83700F540AF /* SectionHeaderFooterView.swift in Sources */,
D23EA802247EBED400D60C34 /* ImageBarButtonItem.swift in Sources */,
AA45AA0B24BF0263007A6EA7 /* LockUpsPlanNamesModel.swift in Sources */,
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
@ -2522,6 +2555,7 @@
D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */,
0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */,
D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */,
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */,
D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */,
@ -2604,6 +2638,7 @@
AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */,
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */,
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */,
@ -2645,6 +2680,7 @@
AA0A257A24766CA200862F64 /* ListLeftVariableIconWithRightCaretBodyText.swift in Sources */,
011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */,
01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */,
D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */,
0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */,
D264FAA7243FE13B00D98315 /* RadioBox.swift in Sources */,
);

View File

@ -149,6 +149,9 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ModuleMolecule.self, viewModelClass: ModuleMoleculeModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: BGImageMolecule.self, viewModelClass: BGImageMoleculeModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeSectionHeader.self, viewModelClass: MoleculeSectionHeaderModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeSectionFooter.self, viewModelClass: MoleculeSectionFooterModel.self)
// MARK:- Other Molecules
MoleculeObjectMapping.shared()?.register(viewClass: DoughnutChartView.self, viewModelClass: DoughnutChartModel.self)

View File

@ -77,7 +77,7 @@ import Foundation
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 120
}

View File

@ -77,7 +77,7 @@ import Foundation
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 120
}

View File

@ -94,7 +94,7 @@
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 120
}

View File

@ -59,7 +59,7 @@
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -55,7 +55,7 @@
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -58,7 +58,7 @@
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -64,7 +64,7 @@
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -90,7 +90,7 @@
rightHeadlineBodyLink.body.setFontStyle(.RegularBodySmall)
}
public override class func estimatedHeight(with molecule: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
public override class func estimatedHeight(with molecule: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}
}

View File

@ -54,7 +54,7 @@
rightDropDown.set(with:model.rightDropDown, delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}
}

View File

@ -59,7 +59,7 @@
rightLabel.setFontStyle(.RegularBodySmall)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 15
}

View File

@ -66,7 +66,7 @@ import Foundation
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -53,9 +53,7 @@ import Foundation
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListOneColumnFullWidthTextDividerSubsectionModel else { return }
headline.set(with: model.headline, delegateObject, additionalData)
body.set(with: model.body, delegateObject, additionalData)
stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData)
updateAccessibilityLabel()
}

View File

@ -16,13 +16,13 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo
public static var identifier: String = "list1CTxtDiv3"
public var headline: LabelModel
public var body: LabelModel
public var body: LabelModel?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(headline: LabelModel, body: LabelModel) {
public init(headline: LabelModel, body: LabelModel?) {
self.headline = headline
self.body = body
super.init()
@ -54,7 +54,7 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
body = try typeContainer.decode(LabelModel.self, forKey: .body)
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
try super.init(from: decoder)
}
@ -63,6 +63,6 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headline, forKey: .headline)
try container.encode(body, forKey: .body)
try container.encodeIfPresent(body, forKey: .body)
}
}

View File

@ -53,9 +53,7 @@ import Foundation
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListOneColumnTextWithWhitespaceDividerShortModel else { return }
headline.set(with: model.headline, delegateObject, additionalData)
body.set(with: model.body, delegateObject, additionalData)
stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData)
updateAccessibilityLabel()
}

View File

@ -16,13 +16,13 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo
public static var identifier: String = "list1CTxtDiv1"
public var headline: LabelModel
public var body: LabelModel
public var body: LabelModel?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(headline: LabelModel, body: LabelModel) {
public init(headline: LabelModel, body: LabelModel?) {
self.headline = headline
self.body = body
super.init()
@ -54,7 +54,7 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
body = try typeContainer.decode(LabelModel.self, forKey: .body)
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
try super.init(from: decoder)
}
@ -63,6 +63,6 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headline, forKey: .headline)
try container.encode(body, forKey: .body)
try container.encodeIfPresent(body, forKey: .body)
}
}

View File

@ -52,9 +52,7 @@ import Foundation
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListOneColumnTextWithWhitespaceDividerTallModel else { return }
headline.set(with: model.headline, delegateObject, additionalData)
body.set(with: model.body, delegateObject, additionalData)
stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData)
updateAccessibilityLabel()
}

View File

@ -16,13 +16,13 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol
public static var identifier: String = "list1CTxtDiv2"
public var headline: LabelModel
public var body: LabelModel
public var body: LabelModel?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(headline: LabelModel, body: LabelModel) {
public init(headline: LabelModel, body: LabelModel?) {
self.headline = headline
self.body = body
super.init()
@ -54,7 +54,7 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
body = try typeContainer.decode(LabelModel.self, forKey: .body)
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
try super.init(from: decoder)
}
@ -63,6 +63,6 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headline, forKey: .headline)
try container.encode(body, forKey: .body)
try container.encodeIfPresent(body, forKey: .body)
}
}

View File

@ -62,7 +62,7 @@ import Foundation
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 120
}

View File

@ -49,7 +49,7 @@ import Foundation
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -61,7 +61,7 @@ import Foundation
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -60,7 +60,7 @@ import Foundation
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -62,7 +62,7 @@ import Foundation
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -61,7 +61,7 @@ import Foundation
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -58,7 +58,7 @@ import Foundation
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}

View File

@ -0,0 +1,57 @@
//
// MoleculeSectionFooter.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 10/5/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class MoleculeSectionFooter: SectionHeaderFooterView {
open var molecule: MoleculeViewProtocol?
public let containerHelper = ContainerHelper()
/// Adds the molecule to the view.
open func addMolecule(_ molecule: MoleculeViewProtocol) {
contentView.addSubview(molecule)
containerHelper.constrainView(molecule)
molecule.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
self.molecule = molecule
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
containerHelper.updateViewMargins(self, model: model as? MoleculeSectionFooterModel, size: size)
contentView.directionalLayoutMargins = directionalLayoutMargins
(molecule as? MVMCoreViewProtocol)?.updateView(size)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? MoleculeSectionFooterModel else { return }
if molecule != nil {
molecule?.set(with: model.molecule, delegateObject, additionalData)
} else if let moleculeView = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: additionalData) {
addMolecule(moleculeView)
}
containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol)
}
open override func reset() {
super.reset()
molecule?.reset()
}
public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return MoleculeContainer.nameForReuse(with: model, delegateObject)
}
public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
return MoleculeContainer.requiredModules(with: model, delegateObject, error: error)
}
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return MoleculeContainer.estimatedHeight(with: model, delegateObject) ?? 80.0
}
}

View File

@ -0,0 +1,31 @@
//
// MoleculeSectionFooterModel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 10/5/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class MoleculeSectionFooterModel: MoleculeContainerModel, SectionListHeaderFooterModel {
public class override var identifier: String {
return "sectionFooter"
}
/// Defaults to set
public override func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
if useVerticalMargins == nil {
useVerticalMargins = true
}
if topPadding == nil {
topPadding = PaddingDefaultVerticalSpacing3
}
if bottomPadding == nil {
bottomPadding = PaddingDefaultVerticalSpacing3
}
}
}

View File

@ -0,0 +1,72 @@
//
// MoleculeSectionHeader.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 10/2/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class MoleculeSectionHeader: SectionHeaderFooterView {
open var molecule: MoleculeViewProtocol?
public let containerHelper = ContainerHelper()
public let line = Line()
/// Adds the molecule to the view.
open func addMolecule(_ molecule: MoleculeViewProtocol) {
contentView.addSubview(molecule)
containerHelper.constrainView(molecule)
molecule.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
self.molecule = molecule
}
public override func setupView() {
super.setupView()
line.setStyle(.thin)
contentView.addSubview(line)
NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true
NSLayoutConstraint.pinViewRight(toSuperview: line, useMargins: true, constant: 0).isActive = true
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
containerHelper.updateViewMargins(self, model: model as? MoleculeSectionHeaderModel, size: size)
contentView.directionalLayoutMargins = directionalLayoutMargins
(molecule as? MVMCoreViewProtocol)?.updateView(size)
line.updateView(size)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? MoleculeSectionHeaderModel else { return }
if molecule != nil {
molecule?.set(with: model.molecule, delegateObject, additionalData)
} else if let moleculeView = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: additionalData) {
addMolecule(moleculeView)
}
containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol)
if let lineModel = model.line {
line.set(with: lineModel, delegateObject, additionalData)
}
}
open override func reset() {
super.reset()
line.setStyle(.thin)
molecule?.reset()
}
public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return MoleculeContainer.nameForReuse(with: model, delegateObject)
}
public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
return MoleculeContainer.requiredModules(with: model, delegateObject, error: error)
}
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return MoleculeContainer.estimatedHeight(with: model, delegateObject) ?? 80.0
}
}

View File

@ -0,0 +1,52 @@
//
// MoleculeSectionHeaderModel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 10/2/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class MoleculeSectionHeaderModel: MoleculeContainerModel, SectionListHeaderFooterModel {
public class override var identifier: String {
return "sectionHeader"
}
public var line: LineModel?
private enum CodingKeys: String, CodingKey {
case line
case backgroundColor
}
/// Defaults to set
public override func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
if useVerticalMargins == nil {
useVerticalMargins = true
}
if topPadding == nil {
topPadding = PaddingDefaultVerticalSpacing3
}
if bottomPadding == nil {
bottomPadding = PaddingDefaultVerticalSpacing3
}
if line == nil {
line = LineModel(type: .thin)
}
}
required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(line, forKey: .line)
}
}

View File

@ -34,26 +34,14 @@ open class MoleculeCollectionViewCell: CollectionViewCell {
}
open override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
guard let moleculeModel = (model as? MoleculeCollectionItemModel)?.molecule else { return "\(self)<>" }
let className = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel)
let moleculeName = className?.nameForReuse(with: moleculeModel, delegateObject) ?? moleculeModel.moleculeName
return "\(self)<\(moleculeName)>"
return MoleculeContainer.nameForReuse(with: model, delegateObject)
}
open override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
guard let moleculeModel = (model as? MoleculeCollectionItemModel)?.molecule,
let theClass = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel)
else { return nil }
return theClass.requiredModules(with: moleculeModel, delegateObject, error: error)
return MoleculeContainer.requiredModules(with: model, delegateObject, error: error)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
guard let model = model as? MoleculeCollectionItemModel,
let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(model.molecule),
let height = classType.estimatedHeight(with: model.molecule, delegateObject)
else { return 100 }
return height + (model.topPadding ?? 0) + (model.bottomPadding ?? 0)
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return MoleculeContainer.estimatedHeight(with: model, delegateObject) ?? 100
}
}

View File

@ -10,7 +10,7 @@ import Foundation
import MVMCore
@objcMembers public class MoleculeListItemModel: ListItemModel, MoleculeModelProtocol {
@objcMembers public class MoleculeListItemModel: ListItemModel, MoleculeContainerModelProtocol, MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------

View File

@ -30,28 +30,16 @@ import UIKit
}
public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule else { return "\(self)<>" }
let className = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel)
let moleculeName = className?.nameForReuse(with: moleculeModel, delegateObject) ?? moleculeModel.moleculeName
return "\(self)<\(moleculeName)>"
return MoleculeContainer.nameForReuse(with: model, delegateObject)
}
public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule,
let theClass = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel)
else { return nil }
return theClass.requiredModules(with: moleculeModel, delegateObject, error: error)
return MoleculeContainer.requiredModules(with: model, delegateObject, error: error)
}
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule,
let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel),
let height = classType.estimatedHeight(with: moleculeModel, delegateObject)
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
guard let height = MoleculeContainer.estimatedHeight(with: model, delegateObject)
else { return 80 }
return max(2 * PaddingDefaultVerticalSpacing3, height)
return height
}
}

View File

@ -157,7 +157,7 @@ import UIKit
bottomRightLabel.setFontStyle(.RegularMicro)
}
public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 34
}

View File

@ -18,6 +18,15 @@ import Foundation
}
public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]?
public var line: LineModel?
/// This template requires content.
func validateModelHasContent() throws {
if header == nil,
molecules?.count ?? 0 == 0,
footer == nil {
throw ModelRegistry.Error.decoderOther(message: "List template requires atleast one of the following: header, footer, molecules")
}
}
//--------------------------------------------------
// MARK: - Initializer
@ -47,6 +56,7 @@ import Foundation
molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
try super.init(from: decoder)
try validateModelHasContent()
}
open override func encode(to encoder: Encoder) throws {

View File

@ -14,24 +14,15 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
// MARK: - Stored Properties
//--------------------------------------------------
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]?
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)]?
var observer: NSKeyValueObservation?
public var templateModel: ListPageTemplateModel?
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
open override func parsePageJSON() throws {
try parseTemplate(json: loadObject?.pageJSON)
try super.parsePageJSON()
}
// For subclassing the model.
open func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> ListPageTemplateModel {
return try decoder.decode(ListPageTemplateModel.self, from: data)
}
open override var loadObject: MVMCoreLoadObject? {
didSet {
@ -50,6 +41,16 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
open override func parsePageJSON() throws {
try parseTemplate(json: loadObject?.pageJSON)
try super.parsePageJSON()
}
// For subclassing the model.
open func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> ListPageTemplateModel {
return try decoder.decode(ListPageTemplateModel.self, from: data)
}
open override func viewForTop() -> UIView {
guard let headerModel = templateModel?.header,
@ -72,21 +73,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
return molecule
}
open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool {
guard super.shouldFinishProcessingLoad(loadObject, error: error) else { return false }
// This template requires atleast one of the three layers.
if templateModel?.header == nil,
templateModel?.molecules?.count ?? 0 == 0,
templateModel?.footer == nil,
let errorObject = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), messageToLog: "List template requires atleast one of the following: header, footer, molecules", code: CoreUIErrorCode.ErrorCodeListMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) {
error.pointee = errorObject
return false
}
return true
}
open override func handleNewData() {
topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false
bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false
@ -109,7 +95,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
}
open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
guard let moleculeInfo = moleculesInfo?[indexPath.row],
guard let moleculeInfo = getMoleculeInfo(for: indexPath),
let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject)
else { return 0 }
@ -122,7 +108,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let moleculeInfo = moleculesInfo?[indexPath.row],
guard let moleculeInfo = getMoleculeInfo(for: indexPath),
let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier)
else { return UITableViewCell() }
@ -175,7 +161,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
var indexPaths: [IndexPath] = []
for molecule in molecules {
if let info = self.getMoleculeInfo(with: molecule) {
if let info = self.createMoleculeInfo(with: molecule) {
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
let index = indexPath.row + 1 + indexPaths.count
self.moleculesInfo?.insert(info, at: index)
@ -211,8 +197,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
// MARK: - Convenience
//--------------------------------------------------
/// Returns the (identifier, class) of the molecule for the given map.
func getMoleculeInfo(with listItem: (ListItemModelProtocol & MoleculeModelProtocol)?) -> (identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)? {
/// Returns the (identifier, class) of the molecule for the given model.
func createMoleculeInfo(with listItem: MoleculeModelProtocol?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? {
guard let listItem = listItem,
let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(listItem)
@ -223,14 +209,19 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
return (moleculeName, moleculeClass, listItem)
}
/// Returns the (identifier, class) of the molecule for the indexPath.
func getMoleculeInfo(for indexPath: IndexPath) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? {
return moleculesInfo?[indexPath.row]
}
/// Sets up the molecule list and ensures no errors loading all content.
func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]? {
func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)]? {
var moleculeList: [(identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)] = []
var moleculeList: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)] = []
if let molecules = templateModel?.molecules {
for molecule in molecules {
if let info = getMoleculeInfo(with: molecule) {
if let info = createMoleculeInfo(with: molecule) {
moleculeList.append(info)
}
}

View File

@ -0,0 +1,137 @@
//
// SectionListTemplate.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 9/25/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class SectionListTemplate: MoleculeListTemplate {
public var sectionMoleculesInfo: [(header: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, footer: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, rows: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)])]?
open override func viewDidLoad() {
super.viewDidLoad()
tableView.sectionHeaderHeight = UITableView.automaticDimension
}
override func setup() {
// Create quick reference
var sectionList: [(header: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, footer: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, rows: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)])] = []
if let sections = (templateModel as? SectionListTemplateModel)?.sections {
for section in sections {
let header = createMoleculeInfo(with: section.header)
let footer = createMoleculeInfo(with: section.footer)
var rows: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)] = []
for row in section.rows {
if let rowInfo = createMoleculeInfo(with: row) {
rows.append(rowInfo)
}
}
sectionList.append((header: header, footer: footer, rows: rows))
}
}
sectionMoleculesInfo = sectionList.count > 0 ? sectionList : nil
}
override func getMoleculeInfo(for indexPath: IndexPath) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? {
return sectionMoleculesInfo?[indexPath.section].rows[indexPath.row]
}
open override func createTableView() -> TableView {
let tableView = TableView(frame: .zero, style: .plain)
tableView.backgroundColor = .clear
tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
tableView.delegate = self
tableView.dataSource = self
tableView.insetsContentViewsToSafeArea = false
return tableView
}
// For subclassing the model.
open override func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> SectionListTemplateModel {
return try decoder.decode(SectionListTemplateModel.self, from: data)
}
open override func registerWithTable() {
super.registerWithTable()
guard let sections = sectionMoleculesInfo else { return }
for section in sections {
if let header = section.header {
tableView.register(header.class, forHeaderFooterViewReuseIdentifier: header.identifier)
}
if let footer = section.footer {
tableView.register(footer.class, forHeaderFooterViewReuseIdentifier: footer.identifier)
}
for row in section.rows {
tableView.register(row.class, forCellReuseIdentifier: row.identifier)
}
}
}
public func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
guard let moleculeInfo = sectionMoleculesInfo?[section].header else {
return CGFloat.leastNormalMagnitude
}
let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject)
return estimatedHeight ?? 80
}
public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
guard (sectionMoleculesInfo?[section].header) != nil else {
return CGFloat.leastNormalMagnitude
}
return UITableView.automaticDimension
}
public func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat {
guard let moleculeInfo = sectionMoleculesInfo?[section].footer else {
return CGFloat.leastNormalMagnitude
}
let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject)
return estimatedHeight ?? 80
}
public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
guard (sectionMoleculesInfo?[section].footer) != nil else {
return CGFloat.leastNormalMagnitude
}
return UITableView.automaticDimension
}
public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard let sectionInfo = sectionMoleculesInfo?[section],
let headerInfo = sectionInfo.header else { return nil }
let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerInfo.identifier)
(header as? MoleculeViewProtocol)?.reset()
(header as? MoleculeViewProtocol)?.set(with: headerInfo.molecule, delegateObjectIVar, nil)
(header as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width)
// Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
header?.layoutIfNeeded()
return header
}
public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
guard let sectionInfo = sectionMoleculesInfo?[section],
let footerInfo = sectionInfo.footer else { return nil }
let footer = tableView.dequeueReusableHeaderFooterView(withIdentifier: footerInfo.identifier)
(footer as? MoleculeViewProtocol)?.reset()
(footer as? MoleculeViewProtocol)?.set(with: footerInfo.molecule, delegateObjectIVar, nil)
(footer as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width)
// Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
footer?.layoutIfNeeded()
return footer
}
open override func getNumberOfSections() -> Int {
return sectionMoleculesInfo?.count ?? 0
}
open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sectionMoleculesInfo?[section].rows.count ?? 0
}
}

View File

@ -0,0 +1,91 @@
//
// SectionListTemplateModel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 9/25/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol SectionListHeaderFooterModel {
}
@objcMembers open class SectionModel: Codable {
public var header: (SectionListHeaderFooterModel & MoleculeModelProtocol)?
public var footer: (SectionListHeaderFooterModel & MoleculeModelProtocol)?
public var rows: [ListItemModelProtocol & MoleculeModelProtocol]
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case header
case footer
case rows
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
rows = try typeContainer.decodeModels(codingKey: .rows)
}
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeModelIfPresent(header, forKey: .header)
try container.encodeModelIfPresent(footer, forKey: .footer)
try container.encodeModels(rows, forKey: .rows)
}
}
@objcMembers open class SectionListTemplateModel: ListPageTemplateModel {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
open override class var identifier: String {
return "sectionList"
}
public var sections: [SectionModel]
override func validateModelHasContent() throws {
if header == nil,
sections.count == 0,
footer == nil {
throw ModelRegistry.Error.decoderOther(message: "Section List template requires atleast one of the following: header, footer, sections")
}
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case sections
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
sections = try typeContainer.decode([SectionModel].self, forKey: .sections)
try super.init(from: decoder)
}
open override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(sections, forKey: .sections)
}
}

View File

@ -0,0 +1,85 @@
//
// SectionHeaderFooterView.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 10/2/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class SectionHeaderFooterView: UITableViewHeaderFooterView, MoleculeViewProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
open var model: MoleculeModelProtocol?
private var initialSetupPerformed = false
//--------------------------------------------------
// MARK: - Initialization
//--------------------------------------------------
public override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
initialSetup()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
initialSetup()
}
public func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
setupView()
}
}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.model = model
if let backgroundColor = model.backgroundColor {
contentView.backgroundColor = backgroundColor.uiColor
}
}
open func reset() {
contentView.backgroundColor = .white
}
// MARK: Overridables
// Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead.
open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return model.moleculeName
}
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return nil
}
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
return nil
}
}
// MARK:- MVMCoreViewProtocol
extension SectionHeaderFooterView: MVMCoreViewProtocol {
open func updateView(_ size: CGFloat) { }
/// Will be called only once.
open func setupView() {
translatesAutoresizingMaskIntoConstraints = false
insetsLayoutMarginsFromSafeArea = false
preservesSuperviewLayoutMargins = false
contentView.insetsLayoutMarginsFromSafeArea = false
contentView.preservesSuperviewLayoutMargins = false
MVMCoreUIUtility.setMarginsFor(self, leading: 0, top: 0, trailing: 0, bottom: 0)
}
}

View File

@ -20,6 +20,7 @@ public extension MVMCoreUIViewControllerMappingObject {
register(template: MoleculeListTemplate.self)
add(toTemplateViewControllerMapping: ["modalList": MVMCoreViewControllerProgrammaticMappingObject(with: ModalMoleculeListTemplate.self)!])
add(toTemplateViewControllerMapping: [SectionListTemplateModel.identifier: MVMCoreViewControllerProgrammaticMappingObject(with: SectionListTemplate.self)!])
register(template: ThreeLayerTemplate.self)
register(template: ThreeLayerCenterTemplate.self)