diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 0c0ccde7..eee508c8 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -120,6 +120,8 @@ D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */; }; D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837E23CCA96400DFE4FC /* TabsModel.swift */; }; D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */; }; + D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */; }; + D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */; }; D296E14722A5984C0051EBE7 /* MVMCoreUIViewConstrainingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */; }; D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -379,6 +381,8 @@ D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsListItemModel.swift; sourceTree = ""; }; D28A837E23CCA96400DFE4FC /* TabsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsModel.swift; sourceTree = ""; }; D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionListItemModel.swift; sourceTree = ""; }; + D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleProgressModel.swift; sourceTree = ""; }; + D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollerModel.swift; sourceTree = ""; }; D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewConstrainingProtocol.h; sourceTree = ""; }; D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsView.m; sourceTree = ""; }; D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLabelsView.h; sourceTree = ""; }; @@ -863,6 +867,7 @@ D274CA322236A78900B01B62 /* StandardFooterView.swift */, 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */, D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, + D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */, D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */, 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */, 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */, @@ -1036,6 +1041,7 @@ 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */, + D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */, 943784F3236B77BB006A1E82 /* GraphView.swift */, 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */, ); @@ -1394,6 +1400,7 @@ 012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */, D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */, 01EB369023609801006832FA /* ListItemModel.swift in Sources */, + D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */, D268C70C2386DFFD007F2C1C /* StackItemModel.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, @@ -1474,6 +1481,7 @@ D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, 94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */, 011B58F423A2CCC80085F53C /* DropDownModel.swift in Sources */, + D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */, D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */, 012A88F123985E0100FE3DA1 /* Color.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift new file mode 100644 index 00000000..20f49dc0 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift @@ -0,0 +1,128 @@ +// +// CircleProgressModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/13/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +public enum GraphSize: String, Codable { + case small, medium, large +} + +public enum GraphStyle: String, Codable { + case unlimited, safetyMode +} + +public class CircleProgressModel: MoleculeProtocol { + public static var identifier: String = "circleProgress" + public var style: GraphStyle = .unlimited { + didSet { + updateStyle() + } + } + + public var size: GraphSize = .small { + didSet { + updateSize() + } + } + public var diameter: CGFloat = 24 + public var lineWidth: CGFloat = 5 + public var clockwise: Bool = true + public var duration : Double = 1.0 + public var colors = [Color]() + public var backgroundColor: Color? + + public init() {} + + enum CircleProgressCodingKeys: String, CodingKey { + case style + case size + case diameter + case lineWidth + case clockwise + case duration + case colors + case backgroundColor + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CircleProgressCodingKeys.self) + if let style = try typeContainer.decodeIfPresent(GraphStyle.self, forKey: .style) { + self.style = style + } + if let size = try typeContainer.decodeIfPresent(GraphSize.self, forKey: .size) { + self.size = size + } + if let diameter = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .diameter) { + self.diameter = diameter + } + if let lineWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .lineWidth) { + self.lineWidth = lineWidth + } + if let clockwise = try typeContainer.decodeIfPresent(Bool.self, forKey: .clockwise) { + self.clockwise = clockwise + } + if let duration = try typeContainer.decodeIfPresent(Double.self, forKey: .duration) { + self.duration = duration + } + if let colors = try typeContainer.decodeIfPresent([Color].self, forKey: .colors) { + self.colors = colors + } + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CircleProgressCodingKeys.self) + try container.encode(style, forKey: .style) + try container.encode(size, forKey: .size) + try container.encode(diameter, forKey: .diameter) + try container.encode(lineWidth, forKey: .lineWidth) + try container.encode(clockwise, forKey: .clockwise) + try container.encode(duration, forKey: .duration) + try container.encode(colors, forKey: .colors) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + } + + func getCGColorsFromArray(_ colorArray: [String]) -> [Color] { + return colorArray.map { (colorString) -> Color in + return Color(uiColor: UIColor.mfGet(forHex: colorString)) + } + } + + func updateStyle() { + switch style { + case .unlimited: + duration = 1.0 + clockwise = true + //current style, only the end part shows darker look + colors = getCGColorsFromArray(["#007AB8","#007AB8","#033554"]) + break + case .safetyMode: + duration = 1.5 + clockwise = true + colors = getCGColorsFromArray(["#CC4D0F","#CC4D0F","AB0309"]) + break + } + } + + func updateSize() { + switch size { + case .small: + diameter = MFSizeObject(standardSize: 20)?.getValueBasedOnApplicationWidth() ?? 20 + lineWidth = MFSizeObject(standardSize: 4)?.getValueBasedOnApplicationWidth() ?? 4 + break + case .medium: + diameter = MFSizeObject(standardSize: 100)?.getValueBasedOnApplicationWidth() ?? 100 + lineWidth = MFSizeObject(standardSize: 8)?.getValueBasedOnApplicationWidth() ?? 8 + break + case .large: + diameter = MFSizeObject(standardSize: 180)?.getValueBasedOnApplicationWidth() ?? 180 + lineWidth = MFSizeObject(standardSize: 12)?.getValueBasedOnApplicationWidth() ?? 12 + break + } + } +} diff --git a/MVMCoreUI/Atoms/Views/GraphView.swift b/MVMCoreUI/Atoms/Views/GraphView.swift index 40c353b2..cda77660 100644 --- a/MVMCoreUI/Atoms/Views/GraphView.swift +++ b/MVMCoreUI/Atoms/Views/GraphView.swift @@ -8,113 +8,13 @@ import UIKit - -enum GraphSize: String { - case small, medium, large -} - -enum GraphStyle: String { - case unlimited, safetyMode -} - -///Graph Object contains properties -public struct GraphObject { - - var style: GraphStyle { - didSet { - updateStyle() - } - } - var size: GraphSize { - didSet { - updateSize() - } - } - var diameter: CGFloat = 24 - var lineWidth: CGFloat = 5 - var clockwise: Bool = true - var duration : Double = 1.0 - var colors = [CGColor]() - - public init(_ json: [AnyHashable : Any]?) { - style = .unlimited - size = .small - guard let json = json else { - return - } - if let styleString = json.optionalStringForKey("style") { - style = GraphStyle(rawValue: styleString) ?? .unlimited - } - if let sizeString = json.optionalStringForKey("size") { - size = GraphSize(rawValue: sizeString) ?? .small - } - updateStyle() - updateSize() - if let diameter = json.optionalCGFloatForKey("diameter") { - self.diameter = diameter - } - if let lineWidth = json.optionalCGFloatForKey("lineWidth") { - self.lineWidth = lineWidth - } - if let clockwise = json.optionalBoolForKey("clockwise") { - self.clockwise = clockwise - } - if let duration = json["duration"] as? Double { - self.duration = duration - } - if let colorArray = json.optionalArrayForKey("colors") as? [String] { - colors = getCGColorsFromArray(colorArray) - } - } - - func getCGColorsFromArray(_ colorArray: [String]) -> [CGColor] { - return colorArray.map { (colorString) -> CGColor in - return UIColor.mfGet(forHex: colorString).cgColor - } - } - - mutating func updateStyle() { - switch style { - case .unlimited: - duration = 1.0 - clockwise = true - //current style, only the end part shows darker look - colors = getCGColorsFromArray(["#007AB8","#007AB8","#033554"]) - break - case .safetyMode: - duration = 1.5 - clockwise = true - colors = getCGColorsFromArray(["#CC4D0F","#CC4D0F","AB0309"]) - break - } - } - - //those are - mutating func updateSize() { - switch size { - case .small: - diameter = MFSizeObject(standardSize: 20)?.getValueBasedOnApplicationWidth() ?? 20 - lineWidth = MFSizeObject(standardSize: 4)?.getValueBasedOnApplicationWidth() ?? 4 - break - case .medium: - diameter = MFSizeObject(standardSize: 100)?.getValueBasedOnApplicationWidth() ?? 100 - lineWidth = MFSizeObject(standardSize: 8)?.getValueBasedOnApplicationWidth() ?? 8 - break - case .large: - diameter = MFSizeObject(standardSize: 180)?.getValueBasedOnApplicationWidth() ?? 180 - lineWidth = MFSizeObject(standardSize: 12)?.getValueBasedOnApplicationWidth() ?? 12 - break - } - } -} - - @objcMembers open class GraphView: View, MVMCoreUIViewConstrainingProtocol { var heightConstraint: NSLayoutConstraint? var gradientLayer: CALayer? - var graphObject: GraphObject? - + var graphModel: CircleProgressModel? { + return model as? CircleProgressModel + } // MARK: setup open override func setupView() { @@ -128,14 +28,14 @@ public struct GraphObject { override open func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? CircleProgressModel else { return } + createGraphCircle(model) + rotationAnimation(model) } override open func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - let object = GraphObject(json) - graphObject = object - createGraphCircle(object) - rotationAnimation(object) + guard let json = json, let model = try? Self.decodeJSONToModel(json: json, type: CircleProgressModel.self) else { return } + setWithModel(model, delegateObject, additionalData) } class func getAngle(_ piValue: Double) -> Double { @@ -147,7 +47,7 @@ public struct GraphObject { } // MARK: circle - open func createGraphCircle(_ graphObject: GraphObject) { + open func createGraphCircle(_ graphObject: CircleProgressModel) { if let sublayers = layer.sublayers { for sublayer in sublayers { sublayer.removeAllAnimations() @@ -188,14 +88,14 @@ public struct GraphObject { | | | ------------- */ - func createGradientLayer(_ graphObject: GraphObject) -> CALayer { + func createGradientLayer(_ graphObject: CircleProgressModel) -> CALayer { let containLayer = CALayer() containLayer.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter) let radius = graphObject.diameter / 2.0 //create graident layers guard graphObject.colors.count > 1 else { - containLayer.backgroundColor = graphObject.colors.first + containLayer.backgroundColor = graphObject.colors.first?.uiColor.cgColor return containLayer } var topGradientHeight : CGFloat = 0.0 @@ -214,7 +114,7 @@ public struct GraphObject { leftColors.removeLast() topLayer.colors = [leftColors.last!, rightColors.first!] } else { - topLayer.backgroundColor = leftColors.last + topLayer.backgroundColor = leftColors.last?.uiColor.cgColor } containLayer.addSublayer(topLayer) @@ -227,7 +127,7 @@ public struct GraphObject { if leftColors.count > 1 { leftLayer.colors = Array(leftColors) } else { - leftLayer.backgroundColor = leftColors.first + leftLayer.backgroundColor = leftColors.first?.uiColor.cgColor } containLayer.addSublayer(leftLayer) @@ -238,7 +138,7 @@ public struct GraphObject { if rightColors.count > 1 { rightLayer.colors = Array(rightColors) } else { - rightLayer.backgroundColor = rightColors.first + rightLayer.backgroundColor = rightColors.first?.uiColor.cgColor } containLayer.addSublayer(rightLayer) @@ -250,7 +150,7 @@ public struct GraphObject { } //MARK: Animation - func rotationAnimation(_ object: GraphObject) { + func rotationAnimation(_ object: CircleProgressModel) { MVMCoreDispatchUtility.performBlock(onMainThread:{ let rotation = CABasicAnimation(keyPath: "transform.rotation") let animationHandler = GraphViewAnimationHandler.shared @@ -281,7 +181,7 @@ public struct GraphObject { extension GraphView: CAAnimationDelegate { public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { - if let object = graphObject { + if let object = graphModel { rotationAnimation(object) } } diff --git a/MVMCoreUI/Models/Template/ListPageTemplateModel.swift b/MVMCoreUI/Models/Template/ListPageTemplateModel.swift index dd8d3979..61729c99 100644 --- a/MVMCoreUI/Models/Template/ListPageTemplateModel.swift +++ b/MVMCoreUI/Models/Template/ListPageTemplateModel.swift @@ -16,12 +16,12 @@ import Foundation public var screenHeading: String? public var isAtomicTabs: Bool? - public var header: HeaderModel? + public var header: MoleculeProtocol? public var molecules: [ListItemModelProtocol] - public var footer: MoleculeStackModel? + public var footer: MoleculeProtocol? public var line: LineModel? - public init(pageType: String, screenHeading: String, molecules: [ListItemModelProtocol]) { + public init(pageType: String, screenHeading: String?, molecules: [ListItemModelProtocol]) { self.pageType = pageType self.screenHeading = screenHeading self.molecules = molecules @@ -48,8 +48,8 @@ import Foundation } self.molecules = molecules isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) - header = try typeContainer.decodeIfPresent(HeaderModel.self, forKey: .header) - footer = try typeContainer.decodeIfPresent(MoleculeStackModel.self, forKey: .footer) + header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header) + footer = try typeContainer.decodeMoleculeIfPresent(codingKey: .footer) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) } @@ -59,8 +59,8 @@ import Foundation try container.encodeIfPresent(screenHeading, forKey: .screenHeading) try container.encodeModels(molecules, forKey: .molecules) try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs) - try container.encodeIfPresent(header, forKey: .header) - try container.encodeIfPresent(footer, forKey: .footer) + try container.encodeModelIfPresent(header, forKey: .header) + try container.encodeModelIfPresent(footer, forKey: .footer) try container.encode(line, forKey: .line) } } diff --git a/MVMCoreUI/Models/Template/StackPageTemplateModel.swift b/MVMCoreUI/Models/Template/StackPageTemplateModel.swift index 0d8bef77..9cce36ab 100644 --- a/MVMCoreUI/Models/Template/StackPageTemplateModel.swift +++ b/MVMCoreUI/Models/Template/StackPageTemplateModel.swift @@ -18,7 +18,41 @@ import Foundation public var isAtomicTabs: Bool? - public var header: HeaderModel? - public var moleculeStack: MoleculeStackModel? - public var footer: FooterModel? + public var header: MoleculeProtocol? + public var moleculeStack: MoleculeStackModel + public var footer: MoleculeProtocol? + + public init(pageType: String, moleculeStack: MoleculeStackModel) { + self.pageType = pageType + self.moleculeStack = moleculeStack + } + + enum CodingKeys: String, CodingKey { + case pageType + case screenHeading + case header + case footer + case moleculeStack + case isAtomicTabs + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + pageType = try typeContainer.decode(String.self, forKey: .pageType) + moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .moleculeStack) + screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading) + isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) + header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header) + footer = try typeContainer.decodeMoleculeIfPresent(codingKey: .footer) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(pageType, forKey: .pageType) + try container.encode(moleculeStack, forKey: .moleculeStack) + try container.encodeIfPresent(screenHeading, forKey: .screenHeading) + try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs) + try container.encodeModelIfPresent(header, forKey: .header) + try container.encodeModelIfPresent(footer, forKey: .footer) + } } diff --git a/MVMCoreUI/Models/Template/ThreeLayerPageTemplateModel.swift b/MVMCoreUI/Models/Template/ThreeLayerPageTemplateModel.swift index b4604fbc..5d4d1b25 100644 --- a/MVMCoreUI/Models/Template/ThreeLayerPageTemplateModel.swift +++ b/MVMCoreUI/Models/Template/ThreeLayerPageTemplateModel.swift @@ -17,7 +17,43 @@ import Foundation public var isAtomicTabs: Bool? - public var header: MoleculeStackModel? - public var middle: MoleculeStackModel? - public var footer: MoleculeStackModel? + public var header: MoleculeProtocol? + public var middle: MoleculeProtocol? + public var footer: MoleculeProtocol? + + public init(pageType: String, header: MoleculeProtocol?, middle: MoleculeProtocol?, footer: MoleculeProtocol?) { + self.pageType = pageType + self.header = header + self.middle = middle + self.footer = footer + } + + enum CodingKeys: String, CodingKey { + case pageType + case screenHeading + case header + case footer + case middle + case isAtomicTabs + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + pageType = try typeContainer.decode(String.self, forKey: .pageType) + screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading) + isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) + header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header) + header = try typeContainer.decodeMoleculeIfPresent(codingKey: .middle) + footer = try typeContainer.decodeMoleculeIfPresent(codingKey: .footer) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(pageType, forKey: .pageType) + try container.encodeIfPresent(screenHeading, forKey: .screenHeading) + try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs) + try container.encodeModelIfPresent(header, forKey: .header) + try container.encodeModelIfPresent(header, forKey: .middle) + try container.encodeModelIfPresent(footer, forKey: .footer) + } } diff --git a/MVMCoreUI/Molecules/ModuleMolecule.swift b/MVMCoreUI/Molecules/ModuleMolecule.swift index 3b49544c..e2411ec0 100644 --- a/MVMCoreUI/Molecules/ModuleMolecule.swift +++ b/MVMCoreUI/Molecules/ModuleMolecule.swift @@ -23,7 +23,7 @@ open class ModuleMolecule: Container { super.setWithModel(model, delegateObject, additionalData) guard let moduleMoleculeModel = model as? ModuleMoleculeModel, - let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMoleculeModel.moduleName) as? MoleculeProtocol else { + let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMoleculeModel.moduleName) else { // Critical error return } @@ -49,7 +49,7 @@ open class ModuleMolecule: Container { public static func estimatedHeight(forRow molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { guard let moduleMolecule = molecule as? ModuleMoleculeModel, - let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMolecule.moduleName) as? MoleculeProtocol, + let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMolecule.moduleName), let classType = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moduleModel) as? ModelMoleculeViewProtocol.Type, let height = classType.estimatedHeight(forRow: moduleModel, delegateObject: delegateObject)else { // Critical error @@ -60,7 +60,7 @@ open class ModuleMolecule: Container { public override func nameForReuse(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { guard let moduleMolecule = model as? ModuleMoleculeModel, - let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMolecule.moduleName) as? MoleculeProtocol, + let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMolecule.moduleName), let classType = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(moduleModel) as? ModelMoleculeViewProtocol, let name = classType.nameForReuse(moduleModel, delegateObject) else { // Critical error @@ -69,7 +69,6 @@ open class ModuleMolecule: Container { return name } - //TODO: Scottt please check this. public static func requiredModules(_ molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { guard let moduleName = (molecule as? ModuleMoleculeModel)?.moduleName, diff --git a/MVMCoreUI/Molecules/Scroller.swift b/MVMCoreUI/Molecules/Scroller.swift index ee83077d..451eba75 100644 --- a/MVMCoreUI/Molecules/Scroller.swift +++ b/MVMCoreUI/Molecules/Scroller.swift @@ -8,7 +8,7 @@ import UIKit -@objcMembers open class Scroller: ViewConstrainingView { +@objcMembers open class Scroller: Container { public let scrollView = UIScrollView(frame: .zero) public let contentView = MVMCoreUICommonViewsUtility.commonView() @@ -20,7 +20,8 @@ import UIKit translatesAutoresizingMaskIntoConstraints = false scrollView.translatesAutoresizingMaskIntoConstraints = false addSubview(scrollView) - pinView(toSuperView: scrollView) + NSLayoutConstraint.constraintPinSubview(toSuperview: scrollView) + contentView.translatesAutoresizingMaskIntoConstraints = false scrollView.addSubview(contentView) NSLayoutConstraint.constraintPinSubview(toSuperview: contentView) let constraint = contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 1.0) @@ -28,39 +29,18 @@ import UIKit constraint.isActive = true } - public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - #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. - setUpDefaultWithModel(model, delegateObject, additionalData) - - guard let model = model, - let moleculeModel = (model as? MoleculeContainerModel)?.molecule else { - return - } - - if molecule == nil { - if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(moleculeModel, delegateObject, true) { - contentView.addSubview(moleculeView) - pinView(toSuperView: moleculeView) - molecule = moleculeView + public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + if let casteModel = model as? ScrollerModel { + if view != nil { + (view as? ModelMoleculeViewProtocol)?.setWithModel(casteModel.molecule, delegateObject, additionalData) + } else { + if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(casteModel.molecule, delegateObject) { + contentView.addSubview(molecule) + molecule.translatesAutoresizingMaskIntoConstraints = false + containerHelper.constrainView(molecule) + } } - } else { - (molecule as? ModelMoleculeViewProtocol)?.setWithModel(moleculeModel, delegateObject, additionalData) } + super.setWithModel(model, 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) -// } -// } } diff --git a/MVMCoreUI/Molecules/ScrollerModel.swift b/MVMCoreUI/Molecules/ScrollerModel.swift new file mode 100644 index 00000000..3fa225fb --- /dev/null +++ b/MVMCoreUI/Molecules/ScrollerModel.swift @@ -0,0 +1,14 @@ +// +// ScrollerModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/13/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +public class ScrollerModel: MoleculeContainerModel, MoleculeProtocol { + public static var identifier: String = "scroller" + public var backgroundColor: Color? +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index a8401d3f..01677585 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -15,7 +15,6 @@ import Foundation ModelRegistry.register(HeadlineBodyModel.self) ModelRegistry.register(MoleculeStackModel.self) ModelRegistry.register(StackItemModel.self) - ModelRegistry.register(ListItemModel.self) ModelRegistry.register(TextFieldModel.self) ModelRegistry.register(LineModel.self) ModelRegistry.register(ProgressBarModel.self) @@ -23,6 +22,14 @@ import Foundation ModelRegistry.register(CaretViewModel.self) ModelRegistry.register(DashLineModel.self) ModelRegistry.register(ImageViewModel.self) + ModelRegistry.register(TabsModel.self) + ModelRegistry.register(ScrollerModel.self) + // list items + ModelRegistry.register(ListItemModel.self) + ModelRegistry.register(DropDownListItemModel.self) + ModelRegistry.register(AccordionListItemModel.self) + ModelRegistry.register(TabsListItemModel.self) + //need to move labelattributemodel to different method ModelRegistry.register(LabelAttributeFontModel.self) ModelRegistry.register(LabelAttributeColorModel.self) diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 13d814e9..03f4e0fc 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -167,7 +167,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol func getMoleculeInfo(with listItem: ListItemModelProtocol?) -> (identifier: String, class: AnyClass, molecule: ListItemModelProtocol)? { guard let listItem = listItem, let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(listItem), - let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol)?.nameForReuse(listItem, delegateObject() as? MVMCoreUIDelegateObject) else { + let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol)?.nameForReuse(listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName else { return nil } return (moleculeName, moleculeClass, listItem) @@ -188,15 +188,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol /// Sets up the header, footer, molecule list and ensures no errors loading all content. func setup() { - var moleculeList: [(identifier: String, class: AnyClass, molecule: ListItemModelProtocol)] = [] - if let molecules = templateModel?.molecules { - for molecule in molecules { - if let info = getMoleculeInfo(with: molecule) { - moleculeList.append(info) - } - } - } - moleculesInfo = moleculeList + moleculesInfo = getMoleculeInfoList() } /// Adds modules from requiredModules() to the MVMCoreViewControllerMapping.requiredModules map.