This commit is contained in:
Suresh, Kamlesh 2019-11-26 19:20:38 -05:00
parent 7b2fc7bfba
commit 5446fb0785
37 changed files with 866 additions and 327 deletions

View File

@ -12,11 +12,23 @@
0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; };
0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; };
0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */; };
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */; };
012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */; };
012A88AF238C626E00FE3DA1 /* CarouselModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */; };
012A88B1238C880100FE3DA1 /* PagingMoleculeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88B0238C880100FE3DA1 /* PagingMoleculeProtocol.swift */; };
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88C1238D7BCA00FE3DA1 /* CarouselItemModel.swift */; };
012A88C4238D86E600FE3DA1 /* CollectionCellMoleculeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88C3238D86E600FE3DA1 /* CollectionCellMoleculeProtocol.swift */; };
012A88C6238DA34000FE3DA1 /* ModuleMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88C5238DA34000FE3DA1 /* ModuleMoleculeModel.swift */; };
012A88C8238DB02000FE3DA1 /* ModelMoleculeDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88C7238DB02000FE3DA1 /* ModelMoleculeDelegateProtocol.swift */; };
012CA98923849699003F810F /* SeperatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA98823849699003F810F /* SeperatorModel.swift */; };
012CA99A2384A687003F810F /* MFTextField+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */; };
012CA99C23859FDC003F810F /* ViewConstrainingView+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA99B23859FDC003F810F /* ViewConstrainingView+ModelExtension.swift */; };
012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */; };
012CA9BE2385C692003F810F /* ConstrainingMoleculeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9BD2385C692003F810F /* ConstrainingMoleculeProtocol.swift */; };
012CA9DE2388723E003F810F /* ListPageTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9DD2388723E003F810F /* ListPageTemplateModel.swift */; };
012CA9E023888AC8003F810F /* StackPageTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9DF23888AC8003F810F /* StackPageTemplateModel.swift */; };
012CA9E223888AED003F810F /* StackCenteredPageTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9E123888AED003F810F /* StackCenteredPageTemplateModel.swift */; };
012CA9E423888B1B003F810F /* ThreeLayerPageTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9E323888B1B003F810F /* ThreeLayerPageTemplateModel.swift */; };
01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */; };
01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D902327ECE600EF99AA /* CornerLabels.swift */; };
01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D922327ECFB00EF99AA /* ProgressBar.swift */; };
@ -232,11 +244,23 @@
0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = "<group>"; };
0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = "<group>"; };
0116A4E4228B19640094F3ED /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = "<group>"; };
012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModelProtocol.swift; sourceTree = "<group>"; };
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateProtocol.swift; sourceTree = "<group>"; };
012A88AE238C626E00FE3DA1 /* CarouselModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselModel.swift; sourceTree = "<group>"; };
012A88B0238C880100FE3DA1 /* PagingMoleculeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PagingMoleculeProtocol.swift; sourceTree = "<group>"; };
012A88C1238D7BCA00FE3DA1 /* CarouselItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItemModel.swift; sourceTree = "<group>"; };
012A88C3238D86E600FE3DA1 /* CollectionCellMoleculeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionCellMoleculeProtocol.swift; sourceTree = "<group>"; };
012A88C5238DA34000FE3DA1 /* ModuleMoleculeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModuleMoleculeModel.swift; sourceTree = "<group>"; };
012A88C7238DB02000FE3DA1 /* ModelMoleculeDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelMoleculeDelegateProtocol.swift; sourceTree = "<group>"; };
012CA98823849699003F810F /* SeperatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeperatorModel.swift; sourceTree = "<group>"; };
012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFTextField+ModelExtension.swift"; sourceTree = "<group>"; };
012CA99B23859FDC003F810F /* ViewConstrainingView+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ViewConstrainingView+ModelExtension.swift"; sourceTree = "<group>"; };
012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFView+ModelExtension.swift"; sourceTree = "<group>"; };
012CA9BD2385C692003F810F /* ConstrainingMoleculeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstrainingMoleculeProtocol.swift; sourceTree = "<group>"; };
012CA9DD2388723E003F810F /* ListPageTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListPageTemplateModel.swift; sourceTree = "<group>"; };
012CA9DF23888AC8003F810F /* StackPageTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackPageTemplateModel.swift; sourceTree = "<group>"; };
012CA9E123888AED003F810F /* StackCenteredPageTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackCenteredPageTemplateModel.swift; sourceTree = "<group>"; };
012CA9E323888B1B003F810F /* ThreeLayerPageTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerPageTemplateModel.swift; sourceTree = "<group>"; };
01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeTableViewCell.swift; sourceTree = "<group>"; };
01509D902327ECE600EF99AA /* CornerLabels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CornerLabels.swift; sourceTree = "<group>"; };
01509D922327ECFB00EF99AA /* ProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = "<group>"; };
@ -462,11 +486,27 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
012A889A238898C600FE3DA1 /* Template */ = {
isa = PBXGroup;
children = (
012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */,
017BEB392360EEB40024EF95 /* PageModel.swift */,
012CA9DD2388723E003F810F /* ListPageTemplateModel.swift */,
012CA9DF23888AC8003F810F /* StackPageTemplateModel.swift */,
012CA9E123888AED003F810F /* StackCenteredPageTemplateModel.swift */,
012CA9E323888B1B003F810F /* ThreeLayerPageTemplateModel.swift */,
);
path = Template;
sourceTree = "<group>";
};
01509D96232803B200EF99AA /* Models */ = {
isa = PBXGroup;
children = (
017BEB392360EEB40024EF95 /* PageModel.swift */,
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */,
01EB3683236097C0006832FA /* MoleculeProtocol.swift */,
012A88B0238C880100FE3DA1 /* PagingMoleculeProtocol.swift */,
012A88C3238D86E600FE3DA1 /* CollectionCellMoleculeProtocol.swift */,
012A889A238898C600FE3DA1 /* Template */,
012CA9BD2385C692003F810F /* ConstrainingMoleculeProtocol.swift */,
946EE1B5237B663A0036751F /* Extensions */,
01EB368723609801006832FA /* Molecules */,
@ -498,6 +538,9 @@
017BEB3F23620A230024EF95 /* TextFieldModel.swift */,
017BEB4123620AD20024EF95 /* FormModelProtocol.swift */,
017BEB7A236763000024EF95 /* LineModel.swift */,
012A88AE238C626E00FE3DA1 /* CarouselModel.swift */,
012A88C1238D7BCA00FE3DA1 /* CarouselItemModel.swift */,
012A88C5238DA34000FE3DA1 /* ModuleMoleculeModel.swift */,
);
path = Molecules;
sourceTree = "<group>";
@ -900,6 +943,7 @@
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */,
D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */,
D296E1402295EBBA0051EBE7 /* MoleculeDelegateProtocol.h */,
012A88C7238DB02000FE3DA1 /* ModelMoleculeDelegateProtocol.swift */,
D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */,
D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */,
017BEB432362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift */,
@ -1135,6 +1179,7 @@
buildActionMask = 2147483647;
files = (
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */,
012CA9E423888B1B003F810F /* ThreeLayerPageTemplateModel.swift in Sources */,
D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */,
DBC4391822442197001AB423 /* CaretView.swift in Sources */,
D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */,
@ -1157,11 +1202,13 @@
D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */,
D2B18B7F2360913400A9AEDC /* Control.swift in Sources */,
D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */,
012A88C8238DB02000FE3DA1 /* ModelMoleculeDelegateProtocol.swift in Sources */,
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */,
D224798C231450C8003FCCF9 /* HeadlineBodySwitch.swift in Sources */,
017BEB442362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift in Sources */,
D29DF17C21E69E1F003B2FB9 /* MFTextButton.m in Sources */,
D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */,
012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */,
D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */,
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */,
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
@ -1173,6 +1220,7 @@
D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */,
D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */,
D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */,
012A88C4238D86E600FE3DA1 /* CollectionCellMoleculeProtocol.swift in Sources */,
017BEB4023620A230024EF95 /* TextFieldModel.swift in Sources */,
D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */,
D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */,
@ -1181,6 +1229,8 @@
012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */,
D29DF25421E6A177003B2FB9 /* MFMdnTextField.m in Sources */,
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
012A88AF238C626E00FE3DA1 /* CarouselModel.swift in Sources */,
012CA9E023888AC8003F810F /* StackPageTemplateModel.swift in Sources */,
D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */,
01EB369023609801006832FA /* ListItemModel.swift in Sources */,
DBEFFA04225A829700230692 /* Label.swift in Sources */,
@ -1198,6 +1248,7 @@
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
01EB368F23609801006832FA /* LabelModel.swift in Sources */,
0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */,
012CA9E223888AED003F810F /* StackCenteredPageTemplateModel.swift in Sources */,
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */,
D22479962316AF6E003FCCF9 /* HeadlineBodyTextButton.swift in Sources */,
D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */,
@ -1214,12 +1265,14 @@
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */,
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
012A88B1238C880100FE3DA1 /* PagingMoleculeProtocol.swift in Sources */,
D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */,
D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */,
D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */,
D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */,
D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */,
D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */,
012CA9DE2388723E003F810F /* ListPageTemplateModel.swift in Sources */,
D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */,
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */,
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */,
@ -1238,6 +1291,7 @@
D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */,
01EB369323609801006832FA /* HeaderModel.swift in Sources */,
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */,
012A88C6238DA34000FE3DA1 /* ModuleMoleculeModel.swift in Sources */,
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */,
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */,
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */,
@ -1246,6 +1300,7 @@
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */,
D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */,
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */,
D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */,
D29DF25121E6A177003B2FB9 /* MFDigitTextBox.m in Sources */,
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */,
@ -1260,6 +1315,7 @@
D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */,
D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */,
D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */,
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */,
D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */,
01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */,

View File

@ -352,46 +352,6 @@
}
- (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
// Only treated as a container if we are constraining a molecule.
if (!self.constrainedView) {
[super setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
}
[self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
if (self.shouldSetupMoleculeFromJSON) {
NSDictionary *moleculeJSON = [json dict:KeyMolecule];
if (self.molecule) {
[self.molecule setWithJSON:moleculeJSON delegateObject:delegateObject additionalData:additionalData];
} else if (moleculeJSON) {
UIView <MVMCoreUIMoleculeViewProtocol>*molecule = [[MVMCoreUIMoleculeMappingObject sharedMappingObject] createMoleculeForJSON:moleculeJSON delegateObject:delegateObject constrainIfNeeded:true];
if (molecule) {
[self addMolecule:molecule];
}
self.molecule = molecule;
[self setMoleculeAccessibility];
}
} else {
[self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
}
NSNumber *useHorizontalMargins = [json optionalNumberForKey:@"useHorizontalMargins"];
if (useHorizontalMargins) {
self.updateViewHorizontalDefaults = [useHorizontalMargins boolValue];
}
NSNumber *useVerticalMargins = [json optionalNumberForKey:@"useVerticalMargins"];
if (useVerticalMargins) {
self.updateViewVerticalDefaults = [useVerticalMargins boolValue];
}
// Set the alignment for the stack in the containing view. The json driven value is for the axis direction alignment.
NSString *alignment = [json string:@"horizontalAlignment"];
if (alignment) {
[self alignHorizontal:[ViewConstrainingView getAlignmentForString:alignment defaultAlignment:UIStackViewAlignmentFill]];
}
alignment = [json string:@"verticalAlignment"];
if (alignment) {
[self alignVertical:[ViewConstrainingView getAlignmentForString:alignment defaultAlignment:UIStackViewAlignmentFill]];
}
if ([self.molecule respondsToSelector:@selector(copyBackgroundColor)] && [self.molecule performSelector:@selector(copyBackgroundColor)]) {
self.backgroundColor = self.molecule.backgroundColor;
}

View File

@ -11,16 +11,19 @@ import Foundation
public extension MFViewController {
@objc func parsePageJSON() {
guard let pageJSON = loadObject?.pageJSON as? [String: AnyHashable] else {
return
}
do {
let pageData = try JSONSerialization.data(withJSONObject: pageJSON)
let decoder = JSONDecoder()
let pageModel = try decoder.decode(PageModel.self, from: pageData)
self.pageModel = pageModel
} catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
}
(self as? TemplateProtocol)?.parseTemplateJSON()
// guard let pageJSON = loadObject?.pageJSON as? [String: AnyHashable] else {
// return
// }
// do {
// let pageData = try JSONSerialization.data(withJSONObject: pageJSON)
// let decoder = JSONDecoder()
//
// let pageModel = try decoder.decode(PageModel.self, from: pageData)
// self.pageModel = pageModel
// } catch {
// MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
// }
}
}

View File

@ -0,0 +1,14 @@
//
// CollectionCellMoleculeProtocol.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/26/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol CollectionCellMoleculeProtocol: MoleculeProtocol {
var peakingUI: Bool? {get}
var peakingArrowColor: String? {get}
}

View File

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

View File

@ -0,0 +1,42 @@
//
// CarouselItemModel.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/26/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class CarouselItemModel: MoleculeProtocol {
public static var identifier: String = "carouselItem"
public var moleculeName: String
public var backgroundColor: String?
public var molecule: MoleculeProtocol?
public init(molecule: MoleculeProtocol?, backgroundColor: String?) {
self.molecule = molecule
self.moleculeName = Self.identifier
self.backgroundColor = backgroundColor
}
enum CodingKeys: String, CodingKey {
case moleculeName
case molecule
case backgroundColor
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
self.moleculeName = try typeContainer.decode(String.self, forKey: .moleculeName)
self.molecule = try typeContainer.decodeIfPresent(codingKey: .molecule)
self.backgroundColor = try typeContainer.decode(String.self, forKey: .backgroundColor)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(self.molecule, forKey: .molecule)
}
}

View File

@ -0,0 +1,74 @@
//
// CarouselModel.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/25/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers public class CarouselModel: MoleculeProtocol {
public static var identifier: String = "carousel"
public var moleculeName: String
public var molecules: [CarouselItemModel]
public var spacing: Float?
public var border: Bool?
public var loop: Bool?
public var height: Float?
public var itemWidthPercent: Float?
public var itemAlignment: String?
public var pagingMolecule: PagingMoleculeProtocol?
public init(molecules: [CarouselItemModel], spacing: Float?, border: Bool?, loop: Bool?, height: Float?, itemWidthPercent: Float?, itemAlignment: String?, pagingMolecule: PagingMoleculeProtocol?){
self.moleculeName = Self.identifier
self.molecules = molecules
self.spacing = spacing
self.border = border
self.loop = loop
self.height = height
self.itemWidthPercent = itemWidthPercent
self.itemAlignment = itemAlignment
self.pagingMolecule = pagingMolecule
}
enum CodingKeys: String, CodingKey {
case moleculeName
case molecules
case spacing
case border
case loop
case height
case itemWidthPercent
case itemAlignment
case pagingMolecule
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
self.moleculeName = try typeContainer.decode(String.self, forKey: .moleculeName)
self.molecules = try typeContainer.decode([CarouselItemModel].self, forKey: .molecules)
self.spacing = try typeContainer.decode(Float.self, forKey: .spacing)
self.border = try typeContainer.decode(Bool.self, forKey: .border)
self.loop = try typeContainer.decode(Bool.self, forKey: .loop)
self.height = try typeContainer.decode(Float.self, forKey: .height)
self.itemWidthPercent = try typeContainer.decode(Float.self, forKey: .itemWidthPercent)
self.itemAlignment = try typeContainer.decode(String.self, forKey: .itemAlignment)
self.pagingMolecule = try typeContainer.decodeIfPresent(codingKey: .pagingMolecule) as? PagingMoleculeProtocol
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(molecules, forKey: .molecules)
try container.encode(spacing, forKey: .spacing)
try container.encode(border, forKey: .border)
try container.encode(loop, forKey: .loop)
try container.encode(height, forKey: .height)
try container.encode(itemWidthPercent, forKey: .itemWidthPercent)
try container.encode(itemAlignment, forKey: .itemAlignment)
try container.encodeIfPresent(self.pagingMolecule, forKey: .pagingMolecule)
}
}

View File

@ -14,16 +14,26 @@ import Foundation
public var molecule: MoleculeProtocol?
public var actionMap: ActionMapModel?
public init(molecule: MoleculeProtocol?, actionMap: ActionMapModel?) {
public var hideArrow: Bool?
public var separator: SeperatorModel?
public var style: String?
public init(molecule: MoleculeProtocol?, actionMap: ActionMapModel?, hideArrow: Bool?, separator: SeperatorModel?, style: String?) {
self.molecule = molecule
self.actionMap = actionMap
self.moleculeName = Self.identifier
self.hideArrow = hideArrow
self.separator = separator
self.style = style
}
enum CodingKeys: String, CodingKey {
case moleculeName
case molecule
case actionMap
case hideArrow
case separator
case style
}
required public init(from decoder: Decoder) throws {
@ -31,6 +41,10 @@ import Foundation
self.moleculeName = try typeContainer.decode(String.self, forKey: .moleculeName)
self.molecule = try typeContainer.decodeIfPresent(codingKey: .molecule)
self.actionMap = try typeContainer.decodeIfPresent(ActionMapModel.self, forKey: .actionMap)
self.hideArrow = try typeContainer.decode(Bool.self, forKey: .hideArrow)
self.separator = try typeContainer.decode(SeperatorModel.self, forKey: .hideArrow)
self.style = try typeContainer.decode(String.self, forKey: .style)
}
public func encode(to encoder: Encoder) throws {
@ -38,5 +52,9 @@ import Foundation
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(self.molecule, forKey: .molecule)
try container.encodeIfPresent(actionMap, forKey: .actionMap)
try container.encodeIfPresent(hideArrow, forKey: .hideArrow)
try container.encodeIfPresent(separator, forKey: .separator)
try container.encodeIfPresent(style, forKey: .style)
}
}

View File

@ -0,0 +1,14 @@
//
// ModuleMoleculeModel.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/26/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
class ModuleMoleculeModel: MoleculeProtocol {
public static var identifier: String = "moduleMolecule"
public var moduleName: String
}

View File

@ -10,27 +10,56 @@ import Foundation
@objcMembers public class MoleculeStackItemModel: MoleculeProtocol {
public static var identifier: String = "stackItem"
public var moleculeName: String?
public var moleculeName: String
public var molecule: MoleculeProtocol?
public init(molecule: MoleculeProtocol?) {
public var spacing: CGFloat?
public var percentage: Int?
public var verticalAlignment: String?
public var horizontalAlignment: String?
public var gone = false
public init(molecule: MoleculeProtocol?, spacing: CGFloat?, percentage: Int?, verticalAlignment: String?, horizontalAlignment: String?, gone: Bool = false) {
self.molecule = molecule
self.moleculeName = Self.identifier
self.spacing = spacing
self.percentage = percentage
self.verticalAlignment = verticalAlignment
self.horizontalAlignment = horizontalAlignment
self.gone = gone
}
enum CodingKeys: String, CodingKey {
case moleculeName
case molecule
case spacing
case percentage
case verticalAlignment
case horizontalAlignment
case gone
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
self.moleculeName = try typeContainer.decode(String.self, forKey: .moleculeName)
self.molecule = try typeContainer.decodeIfPresent(codingKey: .molecule)
self.spacing = try typeContainer.decode(CGFloat.self, forKey: .spacing)
self.percentage = try typeContainer.decode(Int.self, forKey: .percentage)
self.verticalAlignment = try typeContainer.decode(String.self, forKey: .verticalAlignment)
self.horizontalAlignment = try typeContainer.decode(String.self, forKey: .horizontalAlignment)
self.gone = try typeContainer.decode(Bool.self, forKey: .gone)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(self.molecule, forKey: .molecule)
try container.encode(spacing, forKey: .spacing)
try container.encode(percentage, forKey: .percentage)
try container.encode(verticalAlignment, forKey: .verticalAlignment)
try container.encode(horizontalAlignment, forKey: .horizontalAlignment)
try container.encode(gone, forKey: .gone)
}
}

View File

@ -14,17 +14,20 @@ import Foundation
public var moleculeName: String?
public var molecules: [MoleculeStackItemModel]?
public var axis: String?
public var spacing: Float?
public init(axis: String?, molecules: [MoleculeStackItemModel]?) {
public init(axis: String?, molecules: [MoleculeStackItemModel]?, spacing: Float?) {
self.axis = axis
self.molecules = molecules
self.moleculeName = Self.identifier
self.spacing = spacing
}
enum CodingKeys: String, CodingKey {
case moleculeName
case molecules
case axis
case spacing
}
required public init(from decoder: Decoder) throws {
@ -32,6 +35,7 @@ import Foundation
self.moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName)
self.molecules = try typeContainer.decode([MoleculeStackItemModel].self, forKey: .molecules)
self.axis = try typeContainer.decodeIfPresent(String.self, forKey: .axis)
self.spacing = try typeContainer.decodeIfPresent(Float.self, forKey: .spacing)
}
public func encode(to encoder: Encoder) throws {
@ -39,5 +43,6 @@ import Foundation
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(molecules, forKey: .molecules)
try container.encode(axis, forKey: .axis)
try container.encode(spacing, forKey: .spacing)
}
}

View File

@ -8,7 +8,7 @@
import UIKit
class SeperatorModel: MoleculeProtocol {
@objcMembers public class SeperatorModel: MoleculeProtocol {
public static var identifier: String = "line"
public var type: String?
}

View File

@ -0,0 +1,13 @@
//
// PagingMoleculeProtocol.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/25/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol PagingMoleculeProtocol: MoleculeProtocol {
var position: Float? {get}
}

View File

@ -0,0 +1,24 @@
//
// ListPageTemplate.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/22/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class ListPageTemplateModel: TemplateModelProtocol {
public static var identifier: String = "listTemplate"
public var pageType: String
public var screenHeading: String
public var isAtomicTabs: Bool?
public var header: MoleculeStackModel?
public var molecules: [ListItemModel]?
public var footer: MoleculeStackModel?
}

View File

@ -0,0 +1,21 @@
//
// StackCenteredPageTemplate.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/22/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class StackCenteredPageTemplateModel: TemplateModelProtocol {
public static var identifier: String = "stackCenterTemplate"
public var pageType: String
public var screenHeading: String
public var isAtomicTabs: Bool?
}

View File

@ -0,0 +1,24 @@
//
// StackPageTemplate.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/22/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class StackPageTemplateModel: TemplateModelProtocol {
public static var identifier: String = "moleculeStack"
public var pageType: String
public var screenHeading: String
public var isAtomicTabs: Bool?
public var header: MoleculeStackModel?
public var moleculeStack: MoleculeStackModel?
public var footer: MoleculeStackModel?
}

View File

@ -0,0 +1,22 @@
//
// TemplateModelProtocol.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/22/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol TemplateModelProtocol: Model {
var template: String { get }
var pageType: String { get set }
var screenHeading: String { get set }
var isAtomicTabs: Bool? { get set }
}
extension TemplateModelProtocol {
public var template: String {
get { return Self.identifier }
}
}

View File

@ -0,0 +1,24 @@
//
// ThreeLayerPageTemplateModel.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/22/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class ThreeLayerPageTemplateModel: TemplateModelProtocol {
public static var identifier: String = "threeLayer"
public var pageType: String
public var screenHeading: String
public var isAtomicTabs: Bool?
public var header: MoleculeStackModel?
public var middle: MoleculeStackModel?
public var footer: MoleculeStackModel?
}

View File

@ -0,0 +1,29 @@
//
// ModelTemplateProtocol.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/25/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol TemplateProtocol {
var templateModel: TemplateModelProtocol? {get}
func parseTemplateJSON()
func templateData() -> Data?
}
extension TemplateProtocol where Self: MFViewController {
public func templateData() -> Data? {
guard let pageJSON = loadObject?.pageJSON as? [String: AnyHashable] else {
return nil
}
do {
return try JSONSerialization.data(withJSONObject: pageJSON)
} catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
return nil
}
}
}

View File

@ -8,7 +8,8 @@
import UIKit
open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeViewProtocol, MoleculeListCellProtocol {
open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeViewProtocol, MoleculeListCellProtocol, ModelMoleculeViewProtocol {
open var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)?
open var json: [AnyHashable: Any]?
@ -64,47 +65,50 @@ open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeVi
peakingRightArrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
NSLayoutConstraint.scalingPinViewRight(toSuper: peakingRightArrow, ratio: ratio, anchor: contentView.widthAnchor)
}
public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
self.json = json
if let useHorizontalMargins = json?.optionalBoolForKey("useHorizontalMargins") {
public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
guard let collectionModel = model as? CollectionCellMoleculeProtocol else {
return
}
if let useHorizontalMargins = collectionModel.useHorizontalMargins {
updateViewHorizontalDefaults = useHorizontalMargins
}
if let useVerticalMargins = json?.optionalBoolForKey("useVerticalMargins") {
if let useVerticalMargins = collectionModel.useVerticalMargins {
updateViewVerticalDefaults = useVerticalMargins
}
// Handles peaking.
allowsPeaking = json?.optionalBoolForKey("peakingUI") ?? true
if let peakingArrowColor = json?.optionalStringForKey("peakingArrowColor") {
allowsPeaking = collectionModel.peakingUI ?? false
if let peakingArrowColor = collectionModel.peakingArrowColor {
let color = UIColor.mfGet(forHex: peakingArrowColor)
peakingLeftArrow.tintColor = color
peakingRightArrow.tintColor = color
}
if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) {
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
if let backgroundColorString = collectionModel.backgroundColor {
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
}
guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule) else {
guard let moleculeModel = collectionModel.molecule else {
return
}
if molecule == nil {
if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) {
if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(moleculeModel, delegateObject, true) {
contentView.insertSubview(moleculeView, at: 0)
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: true).values))
molecule = moleculeView
}
} else {
molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
(molecule as? ModelMoleculeViewProtocol)?.setWithModel(moleculeModel, delegateObject, additionalData)
}
// This molecule will handle spacing by default.
if let castView = molecule as? MVMCoreUIViewConstrainingProtocol {
castView.shouldSetHorizontalMargins?(false)
castView.shouldSetVerticalMargins?(false)
}
accessibilityElements = molecule?.subviews
}

View File

@ -9,30 +9,27 @@
import UIKit
@objcMembers open class MoleculeTableViewCell: TableViewCell {
// MARK: - MVMCoreUIMoleculeViewProtocol
public override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
guard molecule == nil, let json = json, let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule), let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) else { return }
public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
super.setWithModel(model, delegateObject, additionalData)
guard let model = model,
let moleculeModel = (model as? ConstrainingMoleculeProtocol)?.molecule,
let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(moleculeModel, delegateObject, true) else {
return
}
addMolecule(moleculeView)
}
public override class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) else {
return 80
}
return max(2 * PaddingDefaultVerticalSpacing3, height)
}
public override class func name(forReuse molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
guard let molecule = molecule?.optionalDictionaryForKey(KeyMolecule) else {
public override class func name(forReuse molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
guard let moleculeModel = molecule?.molecule else {
return "\(self)<>"
}
let moleculeName = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) ?? ""
let className = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moleculeModel) as? ModelMoleculeViewProtocol
let moleculeName = (className as? ModelMoleculeViewProtocol.Type)?.name(forReuse: molecule, delegateObject: delegateObject) ?? moleculeModel.moleculeName ?? ""
return "\(self)<\(moleculeName)>"
}
public class func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule),
let theClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON) else {

View File

@ -8,9 +8,11 @@
import UIKit
@objcMembers open class TableViewCell: UITableViewCell, MVMCoreUIMoleculeViewProtocol, MoleculeListCellProtocol {
@objcMembers open class TableViewCell: UITableViewCell, MVMCoreUIMoleculeViewProtocol, MoleculeListCellProtocol, ModelMoleculeViewProtocol {
open var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)?
open var json: [AnyHashable: Any]?
open var listItemModel: ListItemModel?
open var json: [String: Any]?
// In updateView, will set padding to default.
open var updateViewHorizontalDefaults = true
@ -136,46 +138,47 @@ import UIKit
contentView.insetsLayoutMarginsFromSafeArea = false
contentView.preservesSuperviewLayoutMargins = false
}
// MARK: - MVMCoreUIMoleculeViewProtocol
public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
self.json = json
guard let json = json else { return }
style(with: json.optionalStringForKey("style"))
if let useHorizontalMargins = json.optionalBoolForKey("useHorizontalMargins") {
//TODO: Model, Change to model
public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
guard let model = model as? ListItemModel else {
return
}
self.listItemModel = model
style(with: model.style)
if let useHorizontalMargins = model.useHorizontalMargins {
updateViewHorizontalDefaults = useHorizontalMargins
}
if (json.optionalBoolForKey("useVerticalMargins") ?? true) == false {
if (model.useVerticalMargins ?? true) == false {
topMarginPadding = 0
bottomMarginPadding = 0
}
if let backgroundColorString = json.optionalStringForKey(KeyBackgroundColor) {
if let backgroundColorString = model.backgroundColor {
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
}
// Add the caret if there is an action and it's not declared hidden.
if !customAccessoryView {
if let _ = json.optionalDictionaryForKey("actionMap"), !json.boolForKey("hideArrow") {
if let _ = model.actionMap, !(model.hideArrow ?? false) {
addCaretViewAccessory()
} else {
accessoryView = nil
}
}
// override the separator
if let separator = json.optionalDictionaryForKey("separator") {
if let separator = model.separator {
addSeparatorsIfNeeded()
bottomSeparatorView?.setWithJSON(separator, delegateObject: delegateObject, additionalData: additionalData)
(bottomSeparatorView as? ModelMoleculeViewProtocol)?.setWithModel(separator, nil, nil)
}
guard let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule) else { return }
molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
guard let moleculeModel = model.molecule else { return }
(molecule as? ModelMoleculeViewProtocol)?.setWithModel(moleculeModel, delegateObject, additionalData)
// This molecule will by default handle margins.
if let castView = molecule as? MVMCoreUIViewConstrainingProtocol {
castView.shouldSetHorizontalMargins?(false)
@ -189,18 +192,20 @@ import UIKit
styleStandard()
backgroundColor = .white
}
public class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) else {
public static func estimatedHeight(forRow molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
guard let moleculeModel = molecule?.molecule,
let classType = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moleculeModel) as? ModelMoleculeViewProtocol.Type,
let height = classType.estimatedHeight(forRow: moleculeModel, delegateObject: delegateObject) else {
return 80
}
return max(2 * PaddingDefaultVerticalSpacing3, height)
}
public class func name(forReuse molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
return molecule?.optionalStringForKey(KeyMoleculeName) ?? ""
public class func name(forReuse molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
return molecule?.moleculeName ?? ""
}
// MARK: - Arrow
/// Adds the standard mvm style caret to the accessory view
@objc public func addCaretViewAccessory() {
@ -247,6 +252,7 @@ import UIKit
// MARK: - MoleculeListCellProtocol
/// For when the separator between cells shows using json and frequency. Default is type: standard, frequency: allExceptTop.
//TODO: Change to model
public func setSeparatorWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, indexPath: IndexPath) {
addSeparatorsIfNeeded()
if let json = json {
@ -263,7 +269,8 @@ import UIKit
}
public func didSelectCell(atIndex indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
if let actionMap = json?.optionalDictionaryForKey("actionMap") {
//TODO: Use object when handleAction is rewrote to handle action model
if let actionMap = self.listItemModel?.actionMap?.toJSON() {
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
}
}

View File

@ -38,12 +38,13 @@ import UIKit
}
// MARK: - MoleculeDelegateProtocol
public override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
super.setWithModel(model, delegateObject, additionalData)
self.delegateObject = delegateObject
tabs.reloadData()
}
public override func reset() {
super.reset()
topMarginPadding = 8
@ -51,17 +52,21 @@ import UIKit
}
}
//TODO: Models changes
extension TabsTableViewCell: TopTabbarDelegate {
public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool {
if let moleculesArrays = json?.arrayForKey(KeyMolecules), let molecules = moleculesArrays[topTabbar.selectedIndex] as? [[AnyHashable: Any]] {
if let moleculesArrays = json?.arrayForKey(KeyMolecules),
let molecules = moleculesArrays[topTabbar.selectedIndex] as? [[AnyHashable: Any]] {
delegateObject?.moleculeDelegate?.removeMolecules?(molecules, sender: self, animation: index < tabs.selectedIndex ? .right : .left)
}
previousTabIndex = tabs.selectedIndex
return true
}
public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) {
if let moleculesArrays = json?.arrayForKey(KeyMolecules), let molecules = moleculesArrays[index] as? [[AnyHashable: Any]] {
if let moleculesArrays = json?.arrayForKey(KeyMolecules),
let molecules = moleculesArrays[index] as? [[AnyHashable: Any]] {
delegateObject?.moleculeDelegate?.addMolecules?(molecules, sender: self, animation: index < previousTabIndex ? .left : .right)
}
}
@ -71,7 +76,7 @@ extension TabsTableViewCell: TopTabbarDataSource {
public func number(ofTopTabbarItems topTabbar: TopTabbar) -> Int {
return json?.optionalDictionaryForKey("tabs")?.optionalArrayForKey("tabs")?.count ?? 0
}
public func topTabbar(_ topTabbar: TopTabbar, titleForItemAt index: Int) -> String? {
guard let tabs = json?.optionalDictionaryForKey("tabs")?.arrayForKey("tabs"), let label = tabs[index] as? [AnyHashable: Any], let title = label.optionalStringForKey(KeyText) else {
return "Select"

View File

@ -14,15 +14,10 @@
@protocol MVMCoreUIMoleculeViewProtocol <NSObject, MVMCoreViewProtocol>
/// Sets up the ui based on the json
- (void)setWithJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
@optional
// optional func setWithModel(_ model: MoleculeProtocol, _ delegateObject: MVMCoreUIDelegateObject, _ additionalData: [String: AnyHashable])
//Type arguments cannot be applied to non-parameterized class 'NSObject'
//- (void)setWithModel:(nullable NSObject<MoleculeProtocol *>*)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
/// Sets up the ui based on the json
- (void)setWithJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
/// Called after init to provide an early setter for any molecule specific logic
- (void)setAsMolecule;

View File

@ -10,4 +10,15 @@ import Foundation
public protocol ModelMoleculeViewProtocol {
func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String: AnyHashable]?)
static func name(forReuse molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> String?
static func estimatedHeight(forRow molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat?
}
extension ModelMoleculeViewProtocol {
public static func name(forReuse molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
return nil
}
public static func estimatedHeight(forRow molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return nil
}
}

View File

@ -8,7 +8,7 @@
import UIKit
open class ModuleMolecule: ViewConstrainingView {
open class ModuleMolecule: ViewConstrainingView, ModelMoleculeViewProtocol {
open var moduleMolecule: (UIView & MVMCoreUIMoleculeViewProtocol)?
@ -16,33 +16,65 @@ open class ModuleMolecule: ViewConstrainingView {
super.updateView(size)
moduleMolecule?.updateView(size)
}
// MARK: - MVMCoreUIMoleculeViewProtocol
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
guard let moduleName = json?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else {
// Critical error
return
public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String: AnyHashable]?) {
#warning("This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.")
//TODO: This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.
setUpWithModel(model, delegateObject, additionalData)
guard let moduleMoleculeModel = model as? ModuleMoleculeModel,
let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMoleculeModel.moduleName) else {
// Critical error
return
}
if moduleMolecule == nil {
if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: module, delegateObject: delegateObject, constrainIfNeeded: true) {
addSubview(moleculeView)
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: false).values))
moduleMolecule = moleculeView
isAccessibilityElement = false
if moleculeView.accessibilityElements != nil {
accessibilityElements = moleculeView.accessibilityElements
} else {
accessibilityElements = [moleculeView]
}
}
} else {
moduleMolecule?.setWithJSON(module, delegateObject: delegateObject, additionalData: additionalData)
}
// if moduleMolecule == nil {
// MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(<#T##model: MoleculeProtocol##MoleculeProtocol#>, <#T##delegateObject: MVMCoreUIDelegateObject?##MVMCoreUIDelegateObject?#>, <#T##constrainIfNeeded: Bool##Bool#>)
// if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: module, delegateObject: delegateObject, constrainIfNeeded: true) {
// addSubview(moleculeView)
// NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: false).values))
// moduleMolecule = moleculeView
//
// isAccessibilityElement = false
// if moleculeView.accessibilityElements != nil {
// accessibilityElements = moleculeView.accessibilityElements
// } else {
// accessibilityElements = [moleculeView]
// }
// }
// } else {
// moduleMolecule?.setWithJSON(module, delegateObject: delegateObject, additionalData: additionalData)
// }
}
// // MARK: - MVMCoreUIMoleculeViewProtocol
// open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
// super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
//
// guard let moduleName = json?.optionalStringForKey("moduleName"),
// let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else {
// // Critical error
// return
// }
//
// if moduleMolecule == nil {
// if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: module, delegateObject: delegateObject, constrainIfNeeded: true) {
// addSubview(moleculeView)
// NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: false).values))
// moduleMolecule = moleculeView
//
// isAccessibilityElement = false
// if moleculeView.accessibilityElements != nil {
// accessibilityElements = moleculeView.accessibilityElements
// } else {
// accessibilityElements = [moleculeView]
// }
// }
// } else {
// moduleMolecule?.setWithJSON(module, delegateObject: delegateObject, additionalData: additionalData)
// }
// }
open override func setAsMolecule() {
super.setAsMolecule()
@ -55,7 +87,8 @@ open class ModuleMolecule: ViewConstrainingView {
}
public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
guard let moduleName = json?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else {
guard let moduleName = json?.optionalStringForKey("moduleName"),
let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else {
// Critical error
return 0
}
@ -63,7 +96,8 @@ open class ModuleMolecule: ViewConstrainingView {
}
public override class func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
guard let moduleName = molecule?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else {
guard let moduleName = molecule?.optionalStringForKey("moduleName"),
let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else {
// Critical error
return "moduleMolecule<>"
}

View File

@ -27,19 +27,41 @@ import UIKit
constraint.priority = UILayoutPriority(rawValue: 999)
constraint.isActive = true
}
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
guard let json = json, let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule) else {
public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
//super.setWithModel(model, delegateObject, additionalData)
#warning("This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.")
//TODO: This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.
setUpWithModel(model, delegateObject, additionalData)
guard let model = model,
let moleculeModel = (model as? ConstrainingMoleculeProtocol)?.molecule else {
return
}
if molecule == nil {
if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) {
if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(moleculeModel, delegateObject, true) {
contentView.addSubview(moleculeView)
pinView(toSuperView: moleculeView)
molecule = moleculeView
}
} else {
molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
(molecule as? ModelMoleculeViewProtocol)?.setWithModel(moleculeModel, delegateObject, additionalData)
}
}
// open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
// guard let json = json, let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule) else {
// return
// }
// if molecule == nil {
// if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) {
// contentView.addSubview(moleculeView)
// pinView(toSuperView: moleculeView)
// molecule = moleculeView
// }
// } else {
// molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
// }
// }
}

View File

@ -56,7 +56,6 @@ public class StandardHeaderView: ViewConstrainingView, ModelMoleculeViewProtocol
}
open func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
//TODO: Need to create setWithModel in ViewConstraining View
#warning("This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.")
//TODO: This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.

View File

@ -8,7 +8,8 @@
import UIKit
open class Carousel: ViewConstrainingView {
open class Carousel: ViewConstrainingView, ModelMoleculeViewProtocol {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
/// The current index of the collection view. Includes dummy cells when looping.
@ -28,7 +29,7 @@ open class Carousel: ViewConstrainingView {
var numberOfPages = 0
/// The json for the molecules.
var molecules: [[AnyHashable: Any]]?
var molecules: [MoleculeProtocol]?
/// The horizontal alignment of the cell in the collection view. Only noticeable if the itemWidthPercent is less than 100%.
var itemAlignment = UICollectionView.ScrollPosition.left
@ -79,25 +80,37 @@ open class Carousel: ViewConstrainingView {
}
// MARK: - MVMCoreUIMoleculeViewProtocol
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
//TODO: Model, Change to model
public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
guard let caroselModel = model as? CarouselModel else {
return
}
#warning("This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.")
//TODO: This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.
setUpWithModel(caroselModel, delegateObject, additionalData)
collectionView.backgroundColor = backgroundColor
collectionView.layer.borderColor = backgroundColor?.cgColor
collectionView.layer.borderWidth = (json?.boolForKey("border") ?? false) ? 1 : 0
collectionView.layer.borderWidth = (caroselModel.border ?? false) ? 1 : 0
backgroundColor = .white
registerCells(with: json, delegateObject: delegateObject)
setupLayout(with: json)
prepareMolecules(with: json)
itemWidthPercent = (json?.optionalCGFloatForKey("itemWidthPercent") ?? 100) / 100
setAlignment(with: json?.optionalStringForKey("itemAlignment"))
if let height = json?.optionalCGFloatForKey("height") {
collectionViewHeight?.constant = height
registerCells(with: caroselModel, delegateObject: delegateObject)
setupLayout(with: caroselModel)
prepareMolecules(with: caroselModel)
itemWidthPercent = CGFloat((caroselModel.itemWidthPercent ?? 100) / 100)
setAlignment(with: caroselModel.itemAlignment)
if let height = caroselModel.height {
collectionViewHeight?.constant = CGFloat(height)
collectionViewHeight?.isActive = true
}
setupPagingMolecule(json: json?.optionalDictionaryForKey("pagingMolecule"), delegateObject: delegateObject)
setupPagingMolecule(caroselModel.pagingMolecule, delegateObject: delegateObject)
collectionView.reloadData()
}
open override func shouldSetHorizontalMargins(_ shouldSet: Bool) {
super.shouldSetHorizontalMargins(shouldSet)
updateViewHorizontalDefaults = false
@ -105,24 +118,25 @@ open class Carousel: ViewConstrainingView {
// MARK: - JSON Setters
/// Updates the layout being used
func setupLayout(with json:[AnyHashable: Any]?) {
func setupLayout(with carouselModel: CarouselModel?) {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = json?["spacing"] as? CGFloat ?? 1
layout.minimumLineSpacing = CGFloat(carouselModel?.spacing ?? 1)
layout.minimumInteritemSpacing = 0
collectionView.collectionViewLayout = layout
}
func prepareMolecules(with json: [AnyHashable: Any]?) {
guard let newMolecules = json?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] else {
func prepareMolecules(with carouselModel: CarouselModel?) {
guard let newMolecules = carouselModel?.molecules else {
numberOfPages = 0
molecules = nil
return
}
numberOfPages = newMolecules.count
molecules = newMolecules
if json?.boolForKey("loop") ?? false && newMolecules.count > 2 {
if carouselModel?.loop ?? false && newMolecules.count > 2 {
// Sets up the row data with buffer cells on each side (for illusion of endless scroll... also has one more buffer cell on each side in case we can peek that cell).
loop = true
molecules?.insert(newMolecules.last!, at: 0)
@ -132,36 +146,33 @@ open class Carousel: ViewConstrainingView {
}
pageIndex = 0
}
/// Sets up the paging molecule
open func setupPagingMolecule(_ molecule: PagingMoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) {
var pagingView: (UIView & MVMCoreUIPagingProtocol)? = nil
if let molecule = molecule {
pagingView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(molecule, delegateObject, true) as? (UIView & MVMCoreUIPagingProtocol)
}
addPaging(view: pagingView, position: (CGFloat(molecule?.position ?? 20)))
}
/// Registers the cells with the collection view
func registerCells(with json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) {
if let molecules = json?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] {
for molecule in molecules {
if let info = getMoleculeInfo(with: molecule, delegateObject: delegateObject) {
collectionView.register(info.class, forCellWithReuseIdentifier: info.identifier)
}
func registerCells(with carouselModel: CarouselModel, delegateObject: MVMCoreUIDelegateObject?) {
for molecule in carouselModel.molecules {
if let info = getMoleculeInfo(with: molecule, delegateObject: delegateObject) {
collectionView.register(info.class, forCellWithReuseIdentifier: info.identifier)
}
}
}
/// Sets up the paging molecule
open func setupPagingMolecule(json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) {
var pagingView: (UIView & MVMCoreUIPagingProtocol)? = nil
if let json = json {
pagingView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: json, delegateObject: delegateObject, constrainIfNeeded: true) as? (UIView & MVMCoreUIPagingProtocol)
}
addPaging(view: pagingView, position: (json?.optionalCGFloatForKey("position") ?? 20))
}
// MARK: - Convenience
/// Returns the (identifier, class) of the molecule for the given map.
func getMoleculeInfo(with molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> (identifier: String, class: AnyClass, molecule: [AnyHashable: Any])? {
guard let molecule = molecule,
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule),
let moleculeName = moleculeClass.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) else {
return nil
func getMoleculeInfo(with molecule: MoleculeProtocol, delegateObject: MVMCoreUIDelegateObject?) -> (identifier: String, class: AnyClass, molecule: MoleculeProtocol)? {
guard let className = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) ,
let moleculeName = (className as? ModelMoleculeViewProtocol.Type)?.name(forReuse: molecule, delegateObject: delegateObject) ?? molecule.moleculeName else {
return nil
}
return (moleculeName, moleculeClass, molecule)
return (moleculeName, className, molecule)
}
/// Sets the alignment from the string.
@ -272,9 +283,9 @@ extension Carousel: UICollectionViewDataSource {
return UICollectionViewCell()
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: moleculeInfo.identifier, for: indexPath)
if let protocolCell = cell as? MVMCoreUIMoleculeViewProtocol {
if let protocolCell = cell as? MVMCoreUIMoleculeViewProtocol & ModelMoleculeViewProtocol {
protocolCell.reset?()
protocolCell.setWithJSON(moleculeInfo.molecule, delegateObject: nil, additionalData: nil)
protocolCell.setWithModel(moleculeInfo.molecule, nil, nil)
protocolCell.updateView(collectionView.bounds.width)
}
setAccessiblity(cell, index: indexPath.row)

View File

@ -20,21 +20,22 @@ public class StackItem {
self.view = view
}
init(with view: UIView, json: [AnyHashable: Any]?) {
init(with view: UIView, stackItemModel: MoleculeStackItemModel?) {
self.view = view
update(with: json)
update(with: stackItemModel)
}
func update(with json: [AnyHashable: Any]?) {
gone = json?.boolForKey("gone") ?? (json == nil)
spacing = json?.optionalCGFloatForKey("spacing")
percentage = json?["percent"] as? Int
if let alignment = json?.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"verticalAlignment"]) {
func update(with stackItemModel: MoleculeStackItemModel?) {
gone = stackItemModel?.gone ?? false
spacing = stackItemModel?.spacing
percentage = stackItemModel?.percentage
if let alignment = stackItemModel?.verticalAlignment {
verticalAlignment = ViewConstrainingView.getAlignmentFor(alignment, defaultAlignment: .fill)
} else {
verticalAlignment = nil
}
if let alignment = json?.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"horizontalAlignment"]) {
if let alignment = stackItemModel?.horizontalAlignment {
horizontalAlignment = ViewConstrainingView.getAlignmentFor(alignment, defaultAlignment: .fill)
} else {
horizontalAlignment = nil
@ -42,10 +43,11 @@ public class StackItem {
}
}
public class MoleculeStackView: ViewConstrainingView {
public class MoleculeStackView: ViewConstrainingView, ModelMoleculeViewProtocol {
var contentView: UIView = MVMCoreUICommonViewsUtility.commonView()
var items: [StackItem] = []
var useStackSpacingBeforeFirstItem = false
var moleculeStackModel: MoleculeStackModel?
private var moleculesShouldSetHorizontalMargins = false
private var moleculesShouldSetVerticalMargins = false
@ -144,44 +146,53 @@ public class MoleculeStackView: ViewConstrainingView {
}
}
}
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
let previousJSON = self.json
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
//TODO: Model, Change to model
public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
guard let model = model as? MoleculeStackModel else {
return
}
let previousModel = self.moleculeStackModel
self.moleculeStackModel = model
#warning("This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.")
//TODO: This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.
setUpWithModel(model, delegateObject, additionalData)
removeAllItemViews()
// If the items in the stack are the same, just update previous items instead of re-allocating.
var items: [StackItem]?
if MoleculeStackView.name(forReuse: previousJSON, delegateObject: delegateObject) == MoleculeStackView.name(forReuse: json, delegateObject: delegateObject) {
if MoleculeStackView.name(forReuse: previousModel, delegateObject: delegateObject) == MoleculeStackView.name(forReuse: model, delegateObject: delegateObject) {
items = self.items
}
self.items = []
guard let molecules = json?.arrayForKey(KeyMolecules) as? [[String: Any]] else {
guard let molecules = model.molecules else {
return
}
// Sets the stack attributes
setAxisWithJSON(json)
spacing = json?.optionalCGFloatForKey("spacing") ?? 16
// Adds the molecules and sets the json.
for (index, map) in molecules.enumerated() {
if let moleculeJSON = map.optionalDictionaryForKey(KeyMolecule) {
//setAxisWithJSON(json)
spacing = CGFloat(model.spacing ?? 16)
for (index, moleculeContainer) in molecules.enumerated() {
if let stackItemModel = moleculeContainer.molecule as? MoleculeStackItemModel {
var view: UIView?
if let item = items?[index] {
item.update(with: map)
view = item.view
(view as? MVMCoreUIMoleculeViewProtocol)?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: nil)
addStackItem(item, lastItem: index == molecules.count - 1)
} else if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) {
view = molecule
addStackItem(StackItem(with: molecule, json: map), lastItem: index == molecules.count - 1)
}
(view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(moleculesShouldSetHorizontalMargins)
(view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(moleculesShouldSetVerticalMargins)
if let item = items?[index] {
item.update(with: stackItemModel)
view = item.view
(view as? ModelMoleculeViewProtocol)?.setWithModel(stackItemModel, delegateObject, nil)
addStackItem(item, lastItem: index == molecules.count - 1)
} else if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(stackItemModel, delegateObject, true) {
view = moleculeView
addStackItem(StackItem(with: moleculeView, stackItemModel: stackItemModel), lastItem: index == molecules.count - 1)
}
(view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(moleculesShouldSetHorizontalMargins)
(view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(moleculesShouldSetVerticalMargins)
}
}
}
public override class func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {

View File

@ -8,9 +8,15 @@
import Foundation
public extension MVMCoreUIMoleculeMappingObject {
func getMoleculeClass(_ model: MoleculeProtocol) -> AnyClass? {
if let moleculeName = model.moleculeName {
return moleculeMapping.object(forKey: moleculeName) as? AnyClass
}
return nil
}
func createMolecule(_ model: MoleculeProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> (UIView & MVMCoreUIMoleculeViewProtocol)? {
return createMolecule(model, delegateObject, false)
}
@ -25,7 +31,7 @@ public extension MVMCoreUIMoleculeMappingObject {
if let molecule = molecule as? ModelMoleculeViewProtocol {
molecule.setWithModel(model, delegateObject, nil)
} else {
molecule.setWithJSON(model.dictionary, delegateObject: delegateObject, additionalData: nil)
molecule.setWithJSON?(model.dictionary, delegateObject: delegateObject, additionalData: nil)
}
}

View File

@ -29,10 +29,10 @@
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)createMoleculeForName:(nonnull NSString *)name;
/// Creates the molecule for the molecule json.
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)createMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject;
/// Creates the molecule for the molecule json. Also checks if the molecule needs to be constrained for a stack/list style situation.
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)createMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject constrainIfNeeded:(BOOL)constrainIfNeeded;
//- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)createMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject;
//
///// Creates the molecule for the molecule json. Also checks if the molecule needs to be constrained for a stack/list style situation.
//- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)createMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject constrainIfNeeded:(BOOL)constrainIfNeeded;
#pragma mark - Convenience

View File

@ -0,0 +1,14 @@
//
// MoleculeDelegateProtocol.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/26/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol ModelMoleculeDelegateProtocol {
func addMolecules(_ molecules: [MoleculeProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation)
func removeMolecules(_ molecules: [MoleculeProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation)
}

View File

@ -8,9 +8,26 @@
import UIKit
open class MoleculeListTemplate: ThreeLayerTableViewController {
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])]?
open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol, ModelMoleculeDelegateProtocol {
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: MoleculeProtocol)]?
var observer: NSKeyValueObservation?
public var templateModel: TemplateModelProtocol?
public func parseTemplateJSON() {
guard let templateData = templateData() else {
return
}
do {
let decoder = JSONDecoder()
let templateModel = try decoder.decode(ListPageTemplateModel.self, from: templateData)
self.templateModel = templateModel
} catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
}
}
open override var loadObject: MVMCoreLoadObject? {
didSet {
@ -27,21 +44,17 @@ open class MoleculeListTemplate: ThreeLayerTableViewController {
}
open override func viewForTop() -> UIView {
// guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"),
// let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else {
// return super.viewForTop()
// }
guard let moleculeModel = pageModel?.header,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(moleculeModel, delegateObject() as? MVMCoreUIDelegateObject, true) else {
return super.viewForTop()
guard let headerModel = (templateModel as? ListPageTemplateModel)?.header,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(headerModel, delegateObject() as? MVMCoreUIDelegateObject, true) else {
return super.viewForTop()
}
return molecule
}
override open func viewForBottom() -> UIView {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"),
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else {
return super.viewForBottom()
guard let footerModel = (templateModel as? ListPageTemplateModel)?.footer,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(footerModel, delegateObject() as? MVMCoreUIDelegateObject, true) else {
return super.viewForBottom()
}
return molecule
}
@ -64,7 +77,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController {
open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
guard let moleculeInfo = moleculesInfo?[indexPath.row],
let estimatedHeight = moleculeInfo.class.estimatedHeight?(forRow: moleculeInfo.molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) else {
let estimatedHeight = (moleculeInfo.class as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: moleculeInfo.molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) else {
return 0
}
return estimatedHeight
@ -85,7 +98,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController {
}
if let protocolCell = cell as? MVMCoreUIMoleculeViewProtocol {
protocolCell.reset?()
protocolCell.setWithJSON(moleculeInfo.molecule, delegateObject: delegate, additionalData: nil)
(protocolCell as? ModelMoleculeViewProtocol)?.setWithModel(moleculeInfo.molecule, delegate, nil)
protocolCell.updateView(tableView.bounds.width)
}
return cell
@ -126,56 +139,58 @@ open class MoleculeListTemplate: ThreeLayerTableViewController {
}
}
}
open override func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
public func addMolecules(_ molecules: [MoleculeProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// This dispatch is needed to fix a race condition that can occur if this function is called during the table setup.
DispatchQueue.main.async {
guard let indexPath = self.tableView?.indexPath(for: sender) else { return }
var indexPaths: [IndexPath] = []
for molecule in molecules {
if let info = self.getMoleculeInfo(with: molecule) {
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
let index = indexPath.row + 1 + indexPaths.count
self.moleculesInfo?.insert(info, at: index)
indexPaths.append(IndexPath(row: index, section: 0))
}
}
self.tableView?.insertRows(at: indexPaths, with: animation)
self.updateViewConstraints()
self.view.layoutIfNeeded()
}
DispatchQueue.main.async {
guard let indexPath = self.tableView?.indexPath(for: sender) else { return }
var indexPaths: [IndexPath] = []
for molecule in molecules {
if let info = self.getMoleculeInfo(with: molecule) {
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
let index = indexPath.row + 1 + indexPaths.count
self.moleculesInfo?.insert(info, at: index)
indexPaths.append(IndexPath(row: index, section: 0))
}
}
self.tableView?.insertRows(at: indexPaths, with: animation)
self.updateViewConstraints()
self.view.layoutIfNeeded()
}
}
open override func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
public func removeMolecules(_ molecules: [MoleculeProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
var indexPaths: [IndexPath] = []
for molecule in molecules {
if let removeIndex = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
return NSDictionary(dictionary: molecule).isEqual(to: moleculeInfo.molecule)
}) {
moleculesInfo?.remove(at: removeIndex)
indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0))
}
}
//TODO: cehck for molecule protocola eqality
// for molecule in molecules {
// if let removeIndex = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
// return molecule == moleculeInfo.molecule
// }) {
// moleculesInfo?.remove(at: removeIndex)
// indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0))
// }
// }
self.tableView?.deleteRows(at: indexPaths, with: animation)
self.updateViewConstraints()
self.view.layoutIfNeeded()
}
// MARK: - Convenience
/// Returns the (identifier, class) of the molecule for the given map.
func getMoleculeInfo(with molecule: [AnyHashable: Any]?) -> (identifier: String, class: AnyClass, molecule: [AnyHashable: Any])? {
func getMoleculeInfo(with molecule: MoleculeProtocol?) -> (identifier: String, class: AnyClass, molecule: MoleculeProtocol)? {
guard let molecule = molecule,
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule),
let moleculeName = moleculeClass.name?(forReuse: molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) else {
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule),
let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol.Type)?.name(forReuse: molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) ?? molecule.moleculeName else {
return nil
}
return (moleculeName, moleculeClass, molecule)
}
/// Sets up the molecule list and ensures no errors loading all content.
func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])]? {
var moleculeList: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])] = []
if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] {
func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: MoleculeProtocol)]? {
var moleculeList: [(identifier: String, class: AnyClass, molecule: MoleculeProtocol)] = []
if let molecules = (templateModel as? ListPageTemplateModel)?.molecules {
for molecule in molecules {
if let info = getMoleculeInfo(with: molecule) {
moleculeList.append(info)
@ -187,8 +202,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController {
/// Sets up the header, footer, molecule list and ensures no errors loading all content.
func setup() {
var moleculeList: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])] = []
if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] {
var moleculeList: [(identifier: String, class: AnyClass, molecule: MoleculeProtocol)] = []
if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [MoleculeProtocol] {
for molecule in molecules {
if let info = getMoleculeInfo(with: molecule) {
moleculeList.append(info)

View File

@ -8,8 +8,24 @@
import UIKit
open class MoleculeStackTemplate: ThreeLayerViewController {
open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol {
var observer: NSKeyValueObservation?
public var templateModel: TemplateModelProtocol?
public func parseTemplateJSON() {
guard let templateData = templateData() else {
return
}
do {
let decoder = JSONDecoder()
let templateModel = try decoder.decode(StackPageTemplateModel.self, from: templateData)
self.templateModel = templateModel
} catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
}
}
open override var loadObject: MVMCoreLoadObject? {
didSet {
@ -30,29 +46,29 @@ open class MoleculeStackTemplate: ThreeLayerViewController {
}
open override func viewForTop() -> UIView? {
guard let moleculeModel = pageModel?.header,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(moleculeModel, delegateObject() as? MVMCoreUIDelegateObject, true) else {
return nil
guard let headerModel = (templateModel as? StackPageTemplateModel)?.header,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(headerModel, delegateObject() as? MVMCoreUIDelegateObject, true) else {
return nil
}
// guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else {
// return nil
// }
return molecule
}
open override func viewForMiddle() -> UIView? {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack") else {
return nil
guard let moleculeStackModel = (templateModel as? StackPageTemplateModel)?.moleculeStack else {
return nil
}
let stack = MoleculeStackView(frame: .zero)
stack.useStackSpacingBeforeFirstItem = true
stack.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil)
stack.setWithModel(moleculeStackModel, delegateObject() as? MVMCoreUIDelegateObject, nil)
return stack
}
override open func viewForBottom() -> UIView? {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else {
return nil
guard let footerModel = (templateModel as? StackPageTemplateModel)?.footer,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(footerModel, delegateObject() as? MVMCoreUIDelegateObject, true) else {
return nil
}
return molecule
}

View File

@ -8,7 +8,23 @@
import UIKit
@objcMembers open class ThreeLayerTemplate: ThreeLayerViewController {
@objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol {
public var templateModel: TemplateModelProtocol?
public func parseTemplateJSON() {
guard let templateData = templateData() else {
return
}
do {
let decoder = JSONDecoder()
let templateModel = try decoder.decode(StackPageTemplateModel.self, from: templateData)
self.templateModel = templateModel
} catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
}
}
override open func viewDidLoad() {
super.viewDidLoad()
@ -20,24 +36,28 @@ import UIKit
super.newDataBuildScreen()
heightConstraint?.isActive = true
}
open override func viewForTop() -> UIView? {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else {
return nil
guard let headerModel = (templateModel as? ThreeLayerPageTemplateModel)?.header,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(headerModel, delegateObject() as? MVMCoreUIDelegateObject, true) else {
return nil
}
return molecule
}
open override func viewForMiddle() -> UIView? {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("middle"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else {
return nil
guard let middleModel = (templateModel as? ThreeLayerPageTemplateModel)?.middle,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(middleModel, delegateObject() as? MVMCoreUIDelegateObject, true) else {
return nil
}
return molecule
}
override open func viewForBottom() -> UIView? {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else {
return nil
guard let footerModel = (templateModel as? ThreeLayerPageTemplateModel)?.footer,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(footerModel, delegateObject() as? MVMCoreUIDelegateObject, true) else {
return nil
}
return molecule
}