From 790a19b34f2719f616d6178772a7c26c791eead0 Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Fri, 19 Mar 2021 17:04:21 -0400 Subject: [PATCH] initial progress --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++ .../Molecules/Items/TabsListItemModel.swift | 2 +- .../MoleculeContainerModel.swift | 10 ++++ .../MoleculeContainerProtocol.swift | 10 +++- MVMCoreUI/Atomic/Organisms/StackModel.swift | 8 ++- .../Atomic/Organisms/StackModelProtocol.swift | 8 ++- .../MoleculeModelProtocol.swift | 53 ++++++++++++++++++- .../ParentMoleculeModelProtocol.swift | 39 ++++++++++++++ .../TemplateModelProtocol.swift | 1 + .../MoleculeTreeTraversalProtocol.swift | 48 +++++++++++++++++ .../Templates/CollectionTemplateModel.swift | 7 +++ .../Templates/ListPageTemplateModel.swift | 7 +++ .../Atomic/Templates/TemplateModel.swift | 1 + .../Templates/ThreeLayerModelBase.swift | 12 +++++ .../ThreeLayerPageTemplateModel.swift | 7 +++ .../BaseControllers/ViewController.swift | 7 +++ 16 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift create mode 100644 MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 9ba02cb8..664974b2 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -123,6 +123,8 @@ 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; }; 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; }; 279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; }; + 27F6B08826051831008529AA /* MoleculeTreeTraversalProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */; }; + 27F6B08C26052AFF008529AA /* ParentMoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */; }; 27F973532466074500CAB5C5 /* PageBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F973522466074500CAB5C5 /* PageBehavior.swift */; }; 27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */; }; 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; }; @@ -679,6 +681,8 @@ 0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = ""; }; 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = ""; }; 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = ""; }; + 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeTreeTraversalProtocol.swift; sourceTree = ""; }; + 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentMoleculeModelProtocol.swift; sourceTree = ""; }; 27F973522466074500CAB5C5 /* PageBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehavior.swift; sourceTree = ""; }; 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenBrightnessModifierBehavior.swift; sourceTree = ""; }; 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = ""; }; @@ -1147,6 +1151,7 @@ D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */, D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */, D28BA74C248589C800B75CB8 /* TabPageModelProtocol.swift */, + 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */, ); path = ModelProtocols; sourceTree = ""; @@ -2275,6 +2280,7 @@ isa = PBXGroup; children = ( 012A88C7238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift */, + 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */, 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */, D20F3B43252E00E4004B3F56 /* PageProtocol.swift */, 012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */, @@ -2820,6 +2826,7 @@ 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */, D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */, AA2AD118244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift in Sources */, + 27F6B08826051831008529AA /* MoleculeTreeTraversalProtocol.swift in Sources */, D2D3957A252FDBB300047B11 /* ModalSectionListTemplate.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, D28BA741248025A300B75CB8 /* TabBarModel.swift in Sources */, @@ -2945,6 +2952,7 @@ 8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */, D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */, 012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */, + 27F6B08C26052AFF008529AA /* ParentMoleculeModelProtocol.swift in Sources */, 0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */, D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift index c83b8933..d0f13c1f 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift @@ -12,7 +12,7 @@ public class TabsListItemModel: ListItemModel, MoleculeModelProtocol { public static var identifier: String = "tabsListItem" var tabs: TabsModel var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]] - + private enum CodingKeys: String, CodingKey { case moleculeName case tabs diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift index 77b40716..dadf3aa9 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift @@ -48,4 +48,14 @@ open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtoco try container.encodeModel(molecule, forKey: .molecule) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } + + public func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { + let result = nextPartialResult(initialResult, molecule) + return nextPartialResult(result, self) + } + + public func depthFirstTraverse(_ cb: (MoleculeModelProtocol)->Void) { + cb(molecule) + cb(self) + } } diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift index 882cf181..636e7af0 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift @@ -8,6 +8,14 @@ import Foundation -public protocol MoleculeContainerModelProtocol: ContainerModelProtocol { +public protocol MoleculeContainerModelProtocol: ContainerModelProtocol, ParentMoleculeModelProtocol { var molecule: MoleculeModelProtocol { get set } } + +public extension MoleculeContainerModelProtocol { + + var children: [MoleculeModelProtocol] { + return [molecule] + } + +} diff --git a/MVMCoreUI/Atomic/Organisms/StackModel.swift b/MVMCoreUI/Atomic/Organisms/StackModel.swift index d96da035..8b1dcc0f 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModel.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModel.swift @@ -7,7 +7,8 @@ // -@objcMembers public class StackModel: ContainerModel, StackModelProtocol, MoleculeModelProtocol { +@objcMembers public class StackModel: ContainerModel, StackModelProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -24,6 +25,10 @@ public var spacing: CGFloat = StackModel.defaultSpacing public var useStackSpacingBeforeFirstItem = false + public var children: [MoleculeModelProtocol] { + return molecules + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -77,4 +82,5 @@ try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } + } diff --git a/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift b/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift index 54f6c9d0..068418f0 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift @@ -8,9 +8,15 @@ import Foundation -public protocol StackModelProtocol { +public protocol StackModelProtocol: ParentMoleculeModelProtocol { var molecules: [StackItemModelProtocol & MoleculeModelProtocol] { get set } var axis: NSLayoutConstraint.Axis { get set } var spacing: CGFloat { get set } var useStackSpacingBeforeFirstItem: Bool { get set } } + +extension StackModelProtocol { + + public var children: [MoleculeModelProtocol] { return molecules } + +} diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift index 4f0cd296..03c9c596 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift @@ -7,7 +7,7 @@ public enum MolecularError: Swift.Error { } -public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol { +public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol, MoleculeTreeTraversalProtocol { var moleculeName: String { get } var backgroundColor: Color? { get set } } @@ -20,3 +20,54 @@ public extension MoleculeModelProtocol { static var categoryCodingKey: String { "moleculeName" } } + +public extension MoleculeModelProtocol { + + func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { + + return nextPartialResult(initialResult, self) + } + + func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) { + callback(self) + } + +} + +public extension Array where Element == MoleculeModelProtocol { + + func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { + return reduce(initialResult) { (result, molecule) -> Result in + return molecule.reduceDepthFirstTraverse(initialResult: result, nextPartialResult: nextPartialResult) + } + } + + func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) { + forEach { (molecule) in + molecule.depthFirstTraverse(callback: callback) + } + } +} + +// Would prefer these to be defined in MoleculeTreeTraversalProtocol that MoleculeModelProtocol inherits. +public extension Array where Element == MoleculeModelProtocol { + + func countMolecules() -> Int { + return reduce(0) { (accumulator, molecule) in + return accumulator + molecule.countMolecules() + } + } + + func printMolecules() { + forEach { (molecule) in + molecule.printMolecules() + } + } + + func allMoleculesOfType() -> [T] { + return reduce([]) { (accumulator, molecule) in + return accumulator + molecule.allMoleculesOfType() + } + } + +} diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift new file mode 100644 index 00000000..5afa57f7 --- /dev/null +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift @@ -0,0 +1,39 @@ +// +// ParentModelProtocol.swift +// MVMCoreUI +// +// Created by Kyle on 3/19/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol ParentMoleculeModelProtocol: MoleculeModelProtocol { + + var children: [MoleculeModelProtocol] { get } + +} + +public extension ParentMoleculeModelProtocol { + + func reduceDepthFirstTraverse(initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol) -> Result) -> Result { + + let result = children.reduce(initialResult) { (result, molecule) -> Result in + if let additionalParent = molecule as? ParentMoleculeModelProtocol { + return additionalParent.reduceDepthFirstTraverse(initialResult: result, nextPartialResult: nextPartialResult) + } + return molecule.reduceDepthFirstTraverse(initialResult: result, nextPartialResult: nextPartialResult) + } + return nextPartialResult(result, self) + } + + func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) { + children.forEach { (molecule) in + if let additionalParent = molecule as? ParentMoleculeModelProtocol { + additionalParent.depthFirstTraverse(callback: callback) + } + molecule.depthFirstTraverse(callback: callback) + } + callback(self) + } +} diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift index 3ed37d6b..31e5a131 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift @@ -11,6 +11,7 @@ import Foundation public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol { var template: String { get } + var rootMolecules: [MoleculeModelProtocol] { get } } public extension TemplateModelProtocol { diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift new file mode 100644 index 00000000..dc5ff7f2 --- /dev/null +++ b/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift @@ -0,0 +1,48 @@ + +// +// TreeTraversalProtocol.swift +// MVMCoreUI +// +// Created by Kyle on 3/19/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +public protocol MoleculeTreeTraversalProtocol { + + // Future options -- Parent first depth first, leaves only. + + func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result + + func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) + + //func breadthFirstTraverse() +} + +// +// Helper Extensions +// + +extension MoleculeTreeTraversalProtocol { + + func countMolecules() -> Int { + return reduceDepthFirstTraverse(initialResult: 0) { (accumulator, molecule) in + return accumulator + 1 + } + } + + func printMolecules() { + depthFirstTraverse { (molecule) in + print(molecule) + } + } + + func allMoleculesOfType() -> [T] { + return reduceDepthFirstTraverse(initialResult: []) { (accumulator, molecule) in + if let typedMolecule = molecule as? T { + return accumulator + [typedMolecule] + } + return accumulator + } + } + +} diff --git a/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift b/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift index f9d8c0a7..b0f3ae92 100644 --- a/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift @@ -18,6 +18,13 @@ import Foundation } public var molecules: [CollectionItemModelProtocol & MoleculeModelProtocol]? public var columns: Int? + + public override var rootMolecules: [MoleculeModelProtocol] { + if let molecules = molecules { + return super.rootMolecules + molecules + } + return super.rootMolecules + } //-------------------------------------------------- // MARK: - Initializer diff --git a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift index a7c92a08..44868e10 100644 --- a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift @@ -20,6 +20,13 @@ import Foundation public var line: LineModel? public var scrollToRowIndex: Int? + public override var rootMolecules: [MoleculeModelProtocol] { + if let molecules = molecules { + return super.rootMolecules + molecules + } + return super.rootMolecules + } + /// This template requires content. func validateModelHasContent() throws { if header == nil, diff --git a/MVMCoreUI/Atomic/Templates/TemplateModel.swift b/MVMCoreUI/Atomic/Templates/TemplateModel.swift index bb8bb104..c3d9bbbb 100644 --- a/MVMCoreUI/Atomic/Templates/TemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/TemplateModel.swift @@ -30,6 +30,7 @@ import Foundation public var navigationBar: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var formRules: [FormGroupRule]? public var behaviors: [PageBehaviorProtocol]? + public var rootMolecules: [MoleculeModelProtocol] { [] } public var tabBarHidden: Bool = false public var tabBarIndex: Int? diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift index 1120b0e7..405a94ce 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift @@ -9,11 +9,23 @@ import Foundation @objcMembers open class ThreeLayerModelBase: TemplateModel, ThreeLayerTemplateModelProtocol { + public var anchorHeader: Bool = false public var header: MoleculeModelProtocol? public var anchorFooter: Bool = false public var footer: MoleculeModelProtocol? + public override var rootMolecules: [MoleculeModelProtocol] { + var rootMolecules:[MoleculeModelProtocol] = [] + if let header = header { + rootMolecules.append(header) + } + if let footer = footer { + rootMolecules.append(footer) + } + return rootMolecules + } + public override init(pageType: String) { super.init(pageType: pageType) } diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift index c4e93f7a..ced0b9ab 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift @@ -14,6 +14,13 @@ import Foundation } public var middle: MoleculeModelProtocol? + public override var rootMolecules: [MoleculeModelProtocol] { + if let middle = middle { + return super.rootMolecules + [middle] + } + return super.rootMolecules + } + public init(pageType: String, header: MoleculeModelProtocol?, middle: MoleculeModelProtocol?, footer: MoleculeModelProtocol?) { super.init(pageType: pageType) self.header = header diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index a2d82952..701d0fb2 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -336,6 +336,13 @@ import UIKit initialLoad() } + print("total molecules in tree: \(model?.rootMolecules.countMolecules() ?? 0)") + + model?.rootMolecules.printMolecules() + + let allVideoMolecules:[BGVideoImageMoleculeModel] = model?.rootMolecules.allMoleculesOfType() ?? [] + print("video molecules: \(allVideoMolecules.count)") + handleNewDataAndUpdateUI() }