container fixes for modal

This commit is contained in:
Pfeil, Scott Robert 2020-01-07 11:08:00 -05:00
parent 58c4a7fd8d
commit d3e3a6809c
25 changed files with 397 additions and 395 deletions

View File

@ -12,12 +12,11 @@
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 */; };
012A88EE239858E300FE3DA1 /* ContainerMoleculeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88ED239858E300FE3DA1 /* ContainerMoleculeProtocol.swift */; };
012CA98923849699003F810F /* SeperatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA98823849699003F810F /* SeperatorModel.swift */; };
012A88EE239858E300FE3DA1 /* ContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88ED239858E300FE3DA1 /* ContainerModel.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 */; };
012CA9BE2385C692003F810F /* ContainerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9BD2385C692003F810F /* ContainerModelProtocol.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 */; };
@ -234,6 +233,7 @@
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; };
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; };
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; };
D2DEDCB423C3D22700C44CC4 /* MoleculeContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2DEDCB323C3D22700C44CC4 /* MoleculeContainerModel.swift */; };
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; };
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; };
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; };
@ -253,12 +253,11 @@
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>"; };
012A88ED239858E300FE3DA1 /* ContainerMoleculeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerMoleculeProtocol.swift; sourceTree = "<group>"; };
012CA98823849699003F810F /* SeperatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeperatorModel.swift; sourceTree = "<group>"; };
012A88ED239858E300FE3DA1 /* ContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerModel.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>"; };
012CA9BD2385C692003F810F /* ContainerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerModelProtocol.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>"; };
@ -478,6 +477,7 @@
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = "<group>"; };
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = "<group>"; };
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = "<group>"; };
D2DEDCB323C3D22700C44CC4 /* MoleculeContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainerModel.swift; sourceTree = "<group>"; };
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = "<group>"; };
D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = "<group>"; };
@ -508,11 +508,10 @@
01509D96232803B200EF99AA /* Models */ = {
isa = PBXGroup;
children = (
D2DEDCB223C3D17600C44CC4 /* Container */,
0AA33B322398134B0067DD0F /* Primitive Models */,
017BEB392360EEB40024EF95 /* PageModel.swift */,
01EB3683236097C0006832FA /* MoleculeProtocol.swift */,
012A88ED239858E300FE3DA1 /* ContainerMoleculeProtocol.swift */,
012CA9BD2385C692003F810F /* ConstrainingMoleculeProtocol.swift */,
946EE1B5237B663A0036751F /* Extensions */,
01EB368723609801006832FA /* Molecules */,
);
@ -533,7 +532,6 @@
01EB368723609801006832FA /* Molecules */ = {
isa = PBXGroup;
children = (
012CA98823849699003F810F /* SeperatorModel.swift */,
01EB368923609801006832FA /* ListItemModel.swift */,
01EB368A23609801006832FA /* MoleculeStackItemModel.swift */,
01EB368B23609801006832FA /* MoleculeStackModel.swift */,
@ -1079,6 +1077,16 @@
path = BaseClasses;
sourceTree = "<group>";
};
D2DEDCB223C3D17600C44CC4 /* Container */ = {
isa = PBXGroup;
children = (
012A88ED239858E300FE3DA1 /* ContainerModel.swift */,
012CA9BD2385C692003F810F /* ContainerModelProtocol.swift */,
D2DEDCB323C3D22700C44CC4 /* MoleculeContainerModel.swift */,
);
path = Container;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@ -1238,13 +1246,13 @@
buildActionMask = 2147483647;
files = (
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */,
D2DEDCB423C3D22700C44CC4 /* MoleculeContainerModel.swift in Sources */,
D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */,
DBC4391822442197001AB423 /* CaretView.swift in Sources */,
D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */,
012CA9BE2385C692003F810F /* ConstrainingMoleculeProtocol.swift in Sources */,
012CA9BE2385C692003F810F /* ContainerModelProtocol.swift in Sources */,
D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */,
94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */,
012CA98923849699003F810F /* SeperatorModel.swift in Sources */,
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
0AA33B34239813C50067DD0F /* UIColor+Extension.swift in Sources */,
0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */,
@ -1308,7 +1316,7 @@
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */,
012A88EE239858E300FE3DA1 /* ContainerMoleculeProtocol.swift in Sources */,
012A88EE239858E300FE3DA1 /* ContainerModel.swift in Sources */,
D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */,
D282AACB2243C61700C46919 /* ButtonView.swift in Sources */,
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,

View File

@ -16,6 +16,7 @@ extension MFView {
}
}
}
extension ModelMoleculeViewProtocol where Self: MFView {
func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String: AnyHashable]?) {
setUpDefaultWithModel(model, delegateObject, additionalData)

View File

@ -8,7 +8,6 @@
import Foundation
extension ViewConstrainingView {
public func setUpWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String: AnyHashable]?) {
if self.constrainedView == nil {
@ -16,7 +15,7 @@ extension ViewConstrainingView {
}
if shouldSetupMoleculeFromJSON,
let moleculeObject = (model as? ConstrainingMoleculeProtocol)?.molecule {
let moleculeObject = (model as? MoleculeContainerModel)?.molecule {
if molecule != nil {
(molecule as? ModelMoleculeViewProtocol)?.setWithModel(moleculeObject, delegateObject, additionalData)
} else {
@ -30,7 +29,7 @@ extension ViewConstrainingView {
(molecule as? ModelMoleculeViewProtocol)?.setWithModel(model, delegateObject, additionalData)
}
if let containerMoleculeModel = model as? ContainerMoleculeProtocol {
if let containerMoleculeModel = model as? ContainerModelProtocol {
if let useHorizontalMargins = containerMoleculeModel.useHorizontalMargins {
updateViewHorizontalDefaults = useHorizontalMargins
}
@ -39,10 +38,10 @@ extension ViewConstrainingView {
}
if let horizontalAlignment = containerMoleculeModel.horizontalAlignment {
alignHorizontal(ViewConstrainingView.getAlignmentFor(horizontalAlignment, defaultAlignment: .fill))
alignHorizontal(horizontalAlignment)
}
if let verticalAlignment = containerMoleculeModel.verticalAlignment {
alignVertical(ViewConstrainingView.getAlignmentFor(verticalAlignment, defaultAlignment: .fill))
alignVertical(verticalAlignment)
}
}

View File

@ -36,6 +36,10 @@ import UIKit
}
}
public func nameForReuse(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return model?.moleculeName
}
open func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
self.model = model
if let backgroundColorString = model?.backgroundColor {
@ -67,4 +71,3 @@ extension View: MVMCoreUIMoleculeViewProtocol {
backgroundColor = .clear
}
}

View File

@ -8,13 +8,6 @@
import UIKit
public protocol ContainerModelProtocol: Model {
var horizontalAlignment: UIStackView.Alignment? { get set }
var verticalAlignment: UIStackView.Alignment? { get set }
var useHorizontalMargins: Bool? { get set }
var useVerticalMargins: Bool? { get set }
}
public class ContainerHelper: NSObject {
var leftConstraint: NSLayoutConstraint?
var topConstraint: NSLayoutConstraint?
@ -145,15 +138,6 @@ public class ContainerHelper: NSObject {
}
}
func set(with model: ContainerModelProtocol) {
if let horizontalAlignment = model.horizontalAlignment {
alignHorizontal(horizontalAlignment)
}
if let verticalAlignment = model.verticalAlignment {
alignVertical(verticalAlignment)
}
}
static func getAlignment(for string: String) -> UIStackView.Alignment? {
switch string {
case "leading":
@ -184,6 +168,19 @@ public class ContainerHelper: NSObject {
}
}
func updateViewMargins(_ view: UIView, model: ContainerModelProtocol?, size: CGFloat) {
MFStyler.setMarginsFor(view, size: size, defaultHorizontal: model?.useHorizontalMargins ?? false, top: (model?.useVerticalMargins ?? false) ? (model?.topMarginPadding ?? 0) : 0, bottom: (model?.useVerticalMargins ?? false) ? (model?.bottomMarginPadding ?? 0) : 0)
}
func set(with model: ContainerModelProtocol) {
if let horizontalAlignment = model.horizontalAlignment {
alignHorizontal(horizontalAlignment)
}
if let verticalAlignment = model.verticalAlignment {
alignVertical(verticalAlignment)
}
}
func set(with JSON: [AnyHashable: Any]?, for contained: UIView) {
if let horizontalAlignmentString = JSON?.optionalStringForKey("horizontalAlignment"), let alignment = ContainerHelper.getAlignment(for: horizontalAlignmentString) ?? (contained as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() {
alignHorizontal(alignment)
@ -205,8 +202,6 @@ open class Container: View {
var containerModel: ContainerModelProtocol? {
get { return model as? ContainerModelProtocol }
}
var topMarginPadding: CGFloat = 0
var bottomMarginPadding: CGFloat = 0
override open func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
super.setWithModel(model, delegateObject, additionalData)
@ -220,7 +215,7 @@ public extension Container {
override func updateView(_ size: CGFloat) {
super.updateView(size)
(view as? MVMCoreViewProtocol)?.updateView(size)
MFStyler.setMarginsFor(self, size: size, defaultHorizontal: containerModel?.useHorizontalMargins ?? true, top: containerModel?.useHorizontalMargins ?? true ? topMarginPadding : 0, bottom: containerModel?.useHorizontalMargins ?? true ? bottomMarginPadding : 0)
containerHelper.updateViewMargins(self, model: containerModel, size: size)
}
/// Will be called only once.

View File

@ -1,19 +0,0 @@
//
// ConstrainingMoleculeProtocol.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/20/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol ConstrainingMoleculeProtocol: MoleculeProtocol {
var molecule: MoleculeProtocol? { get }
}
extension ConstrainingMoleculeProtocol {
public var molecule: MoleculeProtocol? {
get { return nil }
}
}

View File

@ -0,0 +1,54 @@
//
// ContainerModel.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 12/4/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
public class ContainerModel: ContainerModelProtocol, Codable {
public var horizontalAlignment: UIStackView.Alignment?
public var verticalAlignment: UIStackView.Alignment?
public var useHorizontalMargins: Bool?
public var useVerticalMargins: Bool?
public var topMarginPadding: CGFloat?
public var bottomMarginPadding: CGFloat?
enum CodingKeys: String, CodingKey {
case verticalAlignment
case horizontalAlignment
case useHorizontalMargins
case useVerticalMargins
case topMarginPadding
case bottomMarginPadding
}
public init() {}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
if let verticalAlignmentString = try typeContainer.decodeIfPresent(String.self, forKey: .verticalAlignment) {
verticalAlignment = ContainerHelper.getAlignment(for: verticalAlignmentString)
}
if let horizontalAlignmentString = try typeContainer.decodeIfPresent(String.self, forKey: .horizontalAlignment) {
horizontalAlignment = ContainerHelper.getAlignment(for: horizontalAlignmentString)
}
useHorizontalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useHorizontalMargins)
useVerticalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalMargins)
topMarginPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .topMarginPadding)
bottomMarginPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .bottomMarginPadding)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: verticalAlignment), forKey: .verticalAlignment)
try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: horizontalAlignment), forKey: .horizontalAlignment)
try container.encodeIfPresent(useHorizontalMargins, forKey: .useHorizontalMargins)
try container.encodeIfPresent(useVerticalMargins, forKey: .useVerticalMargins)
try container.encodeIfPresent(topMarginPadding, forKey: .topMarginPadding)
try container.encodeIfPresent(bottomMarginPadding, forKey: .bottomMarginPadding)
}
}

View File

@ -0,0 +1,19 @@
//
// ContainerModelProtocol.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/20/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol ContainerModelProtocol {
var horizontalAlignment: UIStackView.Alignment? { get set }
var verticalAlignment: UIStackView.Alignment? { get set }
var useHorizontalMargins: Bool? { get set }
var useVerticalMargins: Bool? { get set }
var topMarginPadding: CGFloat? { get set }
var bottomMarginPadding: CGFloat? { get set }
}

View File

@ -0,0 +1,34 @@
//
// MoleculeContainerModel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 1/6/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class MoleculeContainerModel: ContainerModel {
public var molecule: MoleculeProtocol
enum MoleculeContainerCodingKeys: String, CodingKey {
case molecule
}
public init(with moleculeModel: MoleculeProtocol) {
molecule = moleculeModel
super.init()
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: MoleculeContainerCodingKeys.self)
molecule = try typeContainer.decodeMolecule(codingKey: .molecule)
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: MoleculeContainerCodingKeys.self)
try container.encodeModel(molecule, forKey: .molecule)
}
}

View File

@ -1,17 +0,0 @@
//
// ContainerMoleculeProtocol.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 12/4/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
protocol ContainerMoleculeProtocol: MoleculeProtocol {
var molecule: MoleculeProtocol? { get }
var useHorizontalMargins: Bool? { get }
var useVerticalMargins: Bool? { get }
var horizontalAlignment: String? { get }
var verticalAlignment: String? { get }
}

View File

@ -8,33 +8,36 @@
import Foundation
@objcMembers public class HeaderModel: ConstrainingMoleculeProtocol {
@objcMembers public class HeaderModel: MoleculeContainerModel, MoleculeProtocol {
public static var identifier: String = "header"
public var moleculeName: String?
public var backgroundColor: String?
public var molecule: MoleculeProtocol?
public var seperator: MoleculeProtocol?
public init(molecule: MoleculeProtocol?) {
self.molecule = molecule
self.moleculeName = Self.identifier
}
public var line: LineModel?
enum CodingKeys: String, CodingKey {
enum HeaderCodingKeys: String, CodingKey {
case moleculeName
case molecule
case separator
case line
}
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.decodeMoleculeIfPresent(codingKey: .molecule)
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: HeaderCodingKeys.self)
moleculeName = try typeContainer.decode(String.self, forKey: .moleculeName)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
// Default Values
if topMarginPadding == nil {
topMarginPadding = PaddingDefaultVerticalSpacing
}
if bottomMarginPadding == nil {
bottomMarginPadding = PaddingDefaultVerticalSpacing
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: HeaderCodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModelIfPresent(self.molecule, forKey: .molecule)
try container.encode(line, forKey: .line)
}
}

View File

@ -8,33 +8,30 @@
import Foundation
@objcMembers public class ListItemModel: MoleculeProtocol {
@objcMembers public class ListItemModel: MoleculeContainerModel, MoleculeProtocol {
public static var identifier: String = "listItem"
public var molecule: MoleculeProtocol?
public var backgroundColor: String?
public var action: ActionModel?
public var line: LineModel?
public init(molecule: MoleculeProtocol?, actionMap: ActionModel?) {
self.molecule = molecule
self.action = actionMap
}
enum CodingKeys: String, CodingKey {
enum ListItemCodingKeys: String, CodingKey {
case moleculeName
case molecule
case action
case line
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
self.molecule = try typeContainer.decodeMoleculeIfPresent(codingKey: .molecule)
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: ListItemCodingKeys.self)
self.action = try typeContainer.decodeIfPresent(ActionModel.self, forKey: .action)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: ListItemCodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModelIfPresent(self.molecule, forKey: .molecule)
try container.encodeIfPresent(action, forKey: .action)
try container.encodeIfPresent(line, forKey: .line)
}
}

View File

@ -8,28 +8,38 @@
import Foundation
@objcMembers public class MoleculeStackItemModel: MoleculeProtocol {
@objcMembers public class MoleculeStackItemModel: MoleculeContainerModel, MoleculeProtocol {
public static var identifier: String = "stackItem"
public var molecule: MoleculeProtocol?
public var backgroundColor: String?
public init(molecule: MoleculeProtocol?) {
self.molecule = molecule
}
enum CodingKeys: String, CodingKey {
case moleculeName
case molecule
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
self.molecule = try typeContainer.decodeMoleculeIfPresent(codingKey: .molecule)
public var spacing: CGFloat?
public var percentage: Int? = 0
public var gone: Bool = false
enum MoleculeStackItemCodingKeys: String, CodingKey {
case spacing
case percentage
case gone
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModelIfPresent(self.molecule, forKey: .molecule)
public override init(with moleculeModel: MoleculeProtocol) {
super.init(with: moleculeModel)
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: MoleculeStackItemCodingKeys.self)
spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing)
percentage = try typeContainer.decodeIfPresent(Int.self, forKey: .percentage)
if let gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone) {
self.gone = gone
}
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: MoleculeStackItemCodingKeys.self)
try container.encodeIfPresent(spacing, forKey: .spacing)
try container.encodeIfPresent(percentage, forKey: .percentage)
try container.encode(gone, forKey: .gone)
}
}

View File

@ -8,23 +8,19 @@
import Foundation
@objcMembers public class MoleculeStackModel: ContainerModelProtocol, MoleculeProtocol {
@objcMembers public class MoleculeStackModel: ContainerModel, MoleculeProtocol {
public static var identifier: String = "moleculeStack"
public var backgroundColor: String?
public var molecules: [StackItemModel]
public var axis: NSLayoutConstraint.Axis? = .vertical
public var spacing: CGFloat?
public var horizontalAlignment: UIStackView.Alignment?
public var verticalAlignment: UIStackView.Alignment?
public var useHorizontalMargins: Bool?
public var useVerticalMargins: Bool?
public var molecules: [MoleculeStackItemModel]
public var axis: NSLayoutConstraint.Axis = .vertical
public var spacing: CGFloat = 16.0
public init(molecules: [StackItemModel]) {
public init(molecules: [MoleculeStackItemModel]) {
self.molecules = molecules
super.init()
}
enum CodingKeys: String, CodingKey {
enum StackCodingKeys: String, CodingKey {
case moleculeName
case molecules
case axis
@ -32,19 +28,23 @@ import Foundation
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decodeMolecules(codingKey: .molecules) as! [StackItemModel]
let typeContainer = try decoder.container(keyedBy: StackCodingKeys.self)
molecules = try typeContainer.decodeMolecules(codingKey: .molecules) as! [MoleculeStackItemModel]
if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) {
axis = optionalAxis
}
spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing)
if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) {
self.spacing = spacing
}
try super.init(from: decoder)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: StackCodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(molecules, forKey: .molecules)
try container.encodeIfPresent(axis?.rawValueString, forKey: .axis)
try container.encodeIfPresent(axis.rawValueString, forKey: .axis)
try container.encodeIfPresent(spacing, forKey: .spacing)
}
}

View File

@ -1,15 +0,0 @@
//
// SeperatorModel.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/19/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
class SeperatorModel: MoleculeProtocol {
public static var identifier: String = "line"
public var backgroundColor: String?
public var type: String?
}

View File

@ -8,81 +8,8 @@
import UIKit
open class StackItemModel: ContainerModelProtocol, MoleculeProtocol {
public static var identifier: String = "stackItem"
public var backgroundColor: String?
public var view: StackItem?
public var molecule: MoleculeProtocol
public var spacing: CGFloat? = 16
public var percentage: Int? = 0
public var verticalAlignment: UIStackView.Alignment?
public var horizontalAlignment: UIStackView.Alignment?
public var useHorizontalMargins: Bool? = false
public var useVerticalMargins: Bool? = false
public var gone: Bool? = false
enum CodingKeys: String, CodingKey {
case molecule
case spacing
case percentage
case verticalAlignment
case horizontalAlignment
case useHorizontalMargins
case useVerticalMargins
case gone
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecule = try typeContainer.decodeMolecule(codingKey: .molecule)
spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing)
percentage = try typeContainer.decodeIfPresent(Int.self, forKey: .percentage)
if let verticalAlignmentString = try typeContainer.decodeIfPresent(String.self, forKey: .verticalAlignment) {
verticalAlignment = ContainerHelper.getAlignment(for: verticalAlignmentString)
}
if let horizontalAlignmentString = try typeContainer.decodeIfPresent(String.self, forKey: .horizontalAlignment) {
horizontalAlignment = ContainerHelper.getAlignment(for: horizontalAlignmentString)
}
useVerticalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalMargins)
useHorizontalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useHorizontalMargins)
gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeModel(molecule, forKey: .molecule)
try container.encodeIfPresent(spacing, forKey: .spacing)
try container.encodeIfPresent(percentage, forKey: .percentage)
try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: verticalAlignment), forKey: .verticalAlignment)
try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: horizontalAlignment), forKey: .horizontalAlignment)
try container.encodeIfPresent(useVerticalMargins, forKey: .useVerticalMargins)
try container.encodeIfPresent(useHorizontalMargins, forKey: .useHorizontalMargins)
try container.encodeIfPresent(gone, forKey: .gone)
}
func update(with json: [AnyHashable: Any]?) {
gone = json?.boolForKey("gone") ?? (json == nil)
spacing = json?.optionalCGFloatForKey("spacing")
percentage = json?["percent"] as? Int
if let horizontalAlignmentString = json?.optionalStringForKey("horizontalAlignment") {
horizontalAlignment = ContainerHelper.getAlignment(for: horizontalAlignmentString)
} else {
horizontalAlignment = nil
}
if let verticalAlignmentString = json?.optionalStringForKey("verticalAlignment") {
verticalAlignment = ContainerHelper.getAlignment(for: verticalAlignmentString)
} else {
verticalAlignment = nil
}
useHorizontalMargins = json?.optionalBoolForKey("useHorizontalMargins") ?? false
useVerticalMargins = json?.optionalBoolForKey("useVerticalMargins") ?? false
}
}
open class StackItem: MoleculeContainer {
var stackItemModel: MoleculeStackItemModel? {
get { return model as? MoleculeStackItemModel }
}
}

View File

@ -10,4 +10,12 @@ import Foundation
public protocol ModelMoleculeViewProtocol {
func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String: AnyHashable]?)
func nameForReuse(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String?
}
extension ModelMoleculeViewProtocol {
public func nameForReuse(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return nil
}
}

View File

@ -8,54 +8,33 @@
import UIKit
open class ModuleMoleculeModel: ContainerModelProtocol {
open class ModuleMoleculeModel: MoleculeProtocol {
public var backgroundColor: String?
public static var identifier: String = "moduleMolecule"
public var molecule: MoleculeProtocol?
public var moduleName: String
public var horizontalAlignment: UIStackView.Alignment? = .fill
public var verticalAlignment: UIStackView.Alignment? = .fill
public var useHorizontalMargins: Bool? = false
public var useVerticalMargins: Bool? = false
enum CodingKeys: String, CodingKey {
case molecule
case moduleName
case horizontalAlignment
case verticalAlignment
case useHorizontalMargins
case useVerticalMargins
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
moduleName = try typeContainer.decode(String.self, forKey:.moduleName)
if let verticalAlignmentString = try typeContainer.decodeIfPresent(String.self, forKey: .verticalAlignment) {
verticalAlignment = ContainerHelper.getAlignment(for: verticalAlignmentString)
}
if let horizontalAlignmentString = try typeContainer.decodeIfPresent(String.self, forKey: .horizontalAlignment) {
horizontalAlignment = ContainerHelper.getAlignment(for: horizontalAlignmentString)
}
useVerticalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalMargins)
useHorizontalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useHorizontalMargins)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moduleName, forKey: .moduleName)
try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: verticalAlignment), forKey: .verticalAlignment)
try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: horizontalAlignment), forKey: .horizontalAlignment)
try container.encodeIfPresent(useVerticalMargins, forKey: .useVerticalMargins)
try container.encodeIfPresent(useHorizontalMargins, forKey: .useHorizontalMargins)
}
}
open class ModuleMolecule: Container {
var moduleMoleculeModel: ModuleMoleculeModel? {
get { return model as? ModuleMoleculeModel }
}
public override func setupView() {
super.setupView()
containerModel = ModuleMoleculeModel()
}
open override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {

View File

@ -24,4 +24,17 @@ open class MoleculeContainer: Container {
}
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
}
public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
if let casteModel = model as? MoleculeContainerModel {
if view != nil {
(view as? ModelMoleculeViewProtocol)?.setWithModel(casteModel.molecule, delegateObject, additionalData)
} else {
if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(casteModel.molecule, delegateObject) {
addAndContain(molecule)
}
}
}
super.setWithModel(model, delegateObject, additionalData)
}
}

View File

@ -9,22 +9,10 @@
import UIKit
open class StandardFooterView: MoleculeContainer {
open override func setupView() {
super.setupView()
topMarginPadding = PaddingDefaultVerticalSpacing
bottomMarginPadding = PaddingDefaultVerticalSpacing
}
public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
if let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) {
return height + PaddingDefaultVerticalSpacing + PaddingDefaultVerticalSpacing
}
return 42
}
open override func reset() {
super.reset()
topMarginPadding = PaddingDefaultVerticalSpacing
bottomMarginPadding = PaddingDefaultVerticalSpacing
}
}

View File

@ -11,6 +11,10 @@ import UIKit
public class StandardHeaderView: MoleculeContainer {
var line: Line?
var headerModel: HeaderModel? {
get { return model as? HeaderModel }
}
// MARK: - MVMCoreViewProtocol
open override func updateView(_ size: CGFloat) {
super.updateView(size)
@ -19,8 +23,6 @@ public class StandardHeaderView: MoleculeContainer {
public override func setupView() {
super.setupView()
topMarginPadding = PaddingDefaultVerticalSpacing
bottomMarginPadding = PaddingDefaultVerticalSpacing
guard line == nil else { return }
let line = Line()
@ -47,7 +49,7 @@ public class StandardHeaderView: MoleculeContainer {
return
}
if let seperatorModel = headerModel.seperator as? LineModel {
if let seperatorModel = headerModel.line {
line?.setWithJSON(seperatorModel.toJSON(), delegateObject: delegateObject, additionalData: additionalData)
}
}
@ -75,8 +77,6 @@ public class StandardHeaderView: MoleculeContainer {
open override func reset() {
super.reset()
line?.style = .heavy
topMarginPadding = PaddingDefaultVerticalSpacing
bottomMarginPadding = PaddingDefaultVerticalSpacing
}
public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {

View File

@ -8,12 +8,25 @@
import UIKit
struct EyebrowHeadlineBodyLinkModel: MoleculeProtocol {
static var identifier: String = "eyebrowHeadlineBodyLink"
var backgroundColor: String?
public var eyeBrow: LabelModel?
public var headline: LabelModel?
public var body: LabelModel?
public var link: LineModel?
}
@objcMembers open class EyebrowHeadlineBodyLink: ViewConstrainingView {
let stack = MoleculeStackView(frame: .zero)
let eyebrow = Label.commonLabelB3(true)
let headline = Label.commonLabelB1(true)
let body = Label.commonLabelB2(true)
let link = MFTextButton(nil, constrainHeight: false, forWidth: MVMCoreUIUtility.getWidth())
var casteModel: EyebrowHeadlineBodyLinkModel? {
get { return model as? EyebrowHeadlineBodyLinkModel }
}
// MARK: - MFViewProtocol
open override func setupView() {
@ -21,17 +34,21 @@ import UIKit
guard stack.superview == nil else {
return
}
stack.spacing = 0
addSubview(stack)
pinView(toSuperView: stack)
stack.addStackItem(StackItemModel(with: StackItem(andContain: eyebrow)), lastItem: false)
stack.addStackItem(StackItemModel(with: StackItem(andContain: headline)), lastItem: false)
stack.addStackItem(StackItemModel(with: StackItem(andContain: body)), lastItem: false)
let eyebrowStackItem = MoleculeStackItemModel(with: casteModel!.eyeBrow!)
let headlineStackItem = MoleculeStackItemModel(with: casteModel!.headline!)
let bodyStackItem = MoleculeStackItemModel(with: casteModel!.body!)
let linkStackItem = MoleculeStackItemModel(with: casteModel!.link!)
// To visually take into account the extra padding in the intrinsic content of a button.
let stackItem = StackItemModel(with: StackItem(andContain: link))
stackItem.spacing = -6
stack.addStackItem(stackItem, lastItem: true)
linkStackItem.spacing = -6
let stackModel = MoleculeStackModel(molecules: [eyebrowStackItem,headlineStackItem,bodyStackItem,linkStackItem])
stackModel.spacing = 0
stack.model = stackModel
stack.stackItems = [StackItem(andContain: eyebrow),StackItem(andContain: headline),StackItem(andContain: body),StackItem(andContain: link)]
addSubview(stack)
pinView(toSuperView: stack)
}
open override func updateView(_ size: CGFloat) {
@ -42,7 +59,7 @@ import UIKit
// MARK: - MVMCoreUIMoleculeViewProtocol
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
eyebrow.setWithJSON(json?.optionalDictionaryForKey("eyebrow"), delegateObject: delegateObject, additionalData: additionalData)
/*eyebrow.setWithJSON(json?.optionalDictionaryForKey("eyebrow"), delegateObject: delegateObject, additionalData: additionalData)
stack.items[0].gone = !eyebrow.hasText
headline.setWithJSON(json?.optionalDictionaryForKey("headline"), delegateObject: delegateObject, additionalData: additionalData)
stack.items[1].gone = !headline.hasText
@ -50,13 +67,13 @@ import UIKit
stack.items[2].gone = !body.hasText
link.setWithJSON(json?.optionalDictionaryForKey("link"), delegateObject: delegateObject, additionalData: additionalData)
stack.items[3].gone = link.titleLabel?.text?.count ?? 0 == 0
stack.restack()
stack.restack()*/
}
open override func reset() {
super.reset()
stack.reset()
stack.spacing = 0
stack.stackModel?.spacing = 0
eyebrow.styleB3(true)
headline.styleB1(true)
body.styleB2(true)

View File

@ -14,6 +14,7 @@ open class MoleculeStackView: Container {
var stackModel: MoleculeStackModel? {
get { return model as? MoleculeStackModel }
}
var stackItems: [StackItem] = []
var moleculesShouldSetHorizontalMargins = false
var moleculesShouldSetVerticalMargins = false
@ -27,15 +28,21 @@ open class MoleculeStackView: Container {
/// Restacks the existing items.
func restack() {
guard let stackItems = stackModel?.molecules else { return }
setWithStackItems(stackItems)
removeAllItemViews()
let stackItems = self.stackItems
self.stackItems = []
let lastItem = stackItems.last(where: { (item) -> Bool in
return !item.stackItemModel!.gone
})
for item in stackItems {
addStackItem(item, lastItem: item === lastItem)
}
}
/// Removes all stack items views from the view.
func removeAllItemViews() {
guard let stackItems = stackModel?.molecules else { return }
for item in stackItems {
item.view?.removeFromSuperview()
item.removeFromSuperview()
}
}
@ -76,9 +83,8 @@ open class MoleculeStackView: Container {
super.updateView(size)
directionalLayoutMargins.leading = 0
directionalLayoutMargins.trailing = 0
guard let stackItems = stackModel?.molecules else { return }
for item in stackItems {
item.view?.updateView(size)
item.updateView(size)
}
}
@ -86,64 +92,58 @@ open class MoleculeStackView: Container {
public override func reset() {
super.reset()
backgroundColor = .clear
guard let stackItems = stackModel?.molecules else { return }
for item in stackItems {
item.view?.reset()
item.reset()
}
}
public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) {
let previousModel = stackModel
super.setWithModel(model, delegateObject, additionalData)
removeAllItemViews()
// If the items in the stack are different, clear them, create new ones.
if (previousModel == nil) || nameForReuse(previousModel, delegateObject) != nameForReuse(model, delegateObject) {
stackItems = []
createStackItemsFromModel(with: delegateObject)
} else if let models = stackModel?.molecules {
for (index, element) in models.enumerated() {
stackItems[index].setWithModel(element, delegateObject, additionalData)
}
}
restack()
stackModel?.useHorizontalMargins = moleculesShouldSetHorizontalMargins
stackModel?.useVerticalMargins = moleculesShouldSetVerticalMargins
}
public override func nameForReuse(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
// This will aggregate names of molecules to make an id.
guard let model = model as? MoleculeStackModel else {
return "stack<>"
}
var name = "stack<"
for case let item in model.molecules {
if let moleculeName = item.molecule.moleculeName {
if let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? ModelMoleculeViewProtocol, let nameForReuse = moleculeClass.nameForReuse(item.molecule, delegateObject) {
name.append(nameForReuse + ",")
} else {
name.append(moleculeName + ",")
}
}
}
name.append(">")
return name
}
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
if model == nil {
model = MoleculeStackModel(molecules: [])
}
let previousJSON = self.json
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
removeAllItemViews()
// If the items in the stack are the same, just update previous items instead of re-allocating.
var items: [StackItemModel]?
if MoleculeStackView.name(forReuse: previousJSON, delegateObject: delegateObject) == MoleculeStackView.name(forReuse: json, delegateObject: delegateObject) {
items = stackModel?.molecules
}
stackModel?.molecules = []
guard let molecules = json?.arrayForKey(KeyMolecules) as? [[String: Any]] else {
return
}
// Sets the stack attributes
stackModel?.axis
setAxisWithJSON(json)
spacing = json?.optionalCGFloatForKey("spacing") ?? 16
// Adds the molecules and sets the json.
for (index, map) in molecules.enumerated() {
var view: UIView?
var stackItemModel: StackItemModel
if let item = items?[index] {
stackItemModel = item
item.update(with: map)
view = item.view
(view as? MVMCoreUIMoleculeViewProtocol)?.setWithJSON(map, delegateObject: delegateObject, additionalData: nil)
addStackItem(item, lastItem: index == molecules.count - 1)
} else {
let stackItem = StackItem()
stackItem.setWithJSON(map, delegateObject: delegateObject, additionalData: additionalData)
view = stackItem
stackItemModel = StackItemModel(with: stackItem, json: map)
addStackItem(stackItemModel, lastItem: index == molecules.count - 1)
}
stackItemModel.useHorizontalMargins = moleculesShouldSetHorizontalMargins
stackItemModel.useVerticalMargins = moleculesShouldSetVerticalMargins
let data = try! JSONSerialization.data(withJSONObject: json!)
let decoder = JSONDecoder()
let model = try! decoder.decode(MoleculeStackModel.self, from: data)
setWithModel(model, delegateObject, additionalData as? [String : AnyHashable])
} else {
setWithModel(model, delegateObject, additionalData as? [String : AnyHashable])
}
}
@ -198,78 +198,76 @@ open class MoleculeStackView: Container {
}
// MARK: - Adding to stack
/// Adds the view to the stack.
func addView(_ view: UIView, lastItem: Bool) {
addStackItem(StackItemModel(with: StackItem(andContain: view)), lastItem: lastItem)
/// Creates all of the stackItems for the stackItemModels
func createStackItemsFromModel(with delegate: MVMCoreUIDelegateObject?) {
guard let stackItemModels = stackModel?.molecules else { return }
for model in stackItemModels {
if let stackItem = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model, delegate) as? StackItem {
stackItems.append(stackItem)
}
}
}
/// Adds the stack item to the stack.
func addStackItem(_ stackItem: StackItemModel, lastItem: Bool) {
guard !stackItem.gone else {
items.append(stackItem)
/// Adds the view to the stack.
func addView(_ view: View, lastItem: Bool) {
guard let model = view.model else { return }
let stackItem = StackItem(andContain: view)
stackItem.model = MoleculeStackItemModel(with: model)
addStackItem(stackItem, lastItem: lastItem)
}
/// Adds the stack item view
private func addStackItem(_ stackItem: StackItem, lastItem: Bool) {
let stackModel = self.stackModel!
let model = stackItem.stackItemModel!
guard !model.gone else {
// Gone views do not show
return
}
let view = stackItem.view
contentView.addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(stackItem)
stackItem.translatesAutoresizingMaskIntoConstraints = false
let spacing = stackItem.spacing ?? self.spacing
let verticalAlignment = stackItem.verticalAlignment ?? (stackItem.percentage == nil && axis == .vertical ? .fill : (axis == .vertical ? .leading : .center))
let horizontalAlignment = stackItem.horizontalAlignment ?? (view.view as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() ?? (axis == .vertical || stackItem.percentage == nil ? .fill : .leading)
view.containerHelper.alignHorizontal(horizontalAlignment)
view.containerHelper.alignVertical(verticalAlignment)
let spacing = model.spacing ?? stackModel.spacing
let verticalAlignment = model.verticalAlignment ?? (stackItem.view as? MVMCoreUIViewConstrainingProtocol)?.verticalAlignment?() ?? (model.percentage == nil && stackModel.axis == .vertical ? .fill : (stackModel.axis == .vertical ? .leading : .center))
let horizontalAlignment = model.horizontalAlignment ?? (stackItem.view as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() ?? (stackModel.axis == .vertical || model.percentage == nil ? .fill : .leading)
stackItem.containerHelper.alignHorizontal(horizontalAlignment)
stackItem.containerHelper.alignVertical(verticalAlignment)
let first = items.first { !$0.gone } == nil
if axis == .vertical {
let first = stackItems.first { !($0.stackItemModel?.gone ?? false) } == nil
if stackModel.axis == .vertical {
if first {
pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0)
} else if let previousView = items.last(where: { stackItem in
return !stackItem.gone
})?.view {
view.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: spacing).isActive = true
pinView(stackItem, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0)
} else if let previousView = stackItems.last(where: { item in
return !item.stackItemModel!.gone
}) {
stackItem.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: spacing).isActive = true
}
pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0)
pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0)
if let percent = stackItem.percentage {
view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: CGFloat(percent)/100.0).isActive = true
pinView(stackItem, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0)
pinView(contentView, toView: stackItem, attribute: .trailing, relation: .equal, priority: .required, constant: 0)
if let percent = model.percentage {
stackItem.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: CGFloat(percent)/100.0).isActive = true
}
if lastItem {
pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
pinView(contentView, toView: stackItem, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
}
} else {
if first {
// First horizontal item has no spacing by default unless told otherwise.
pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0)
} else if let previousView = items.last(where: { stackItem in
return !stackItem.gone
})?.view {
view.leftAnchor.constraint(equalTo: previousView.rightAnchor, constant: spacing).isActive = true
pinView(stackItem, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0)
} else if let previousView = stackItems.last(where: { item in
return !item.stackItemModel!.gone
}) {
stackItem.leftAnchor.constraint(equalTo: previousView.rightAnchor, constant: spacing).isActive = true
}
pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0)
pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
if let percent = stackItem.percentage {
view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: CGFloat(percent)/100.0).isActive = true
pinView(stackItem, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0)
pinView(contentView, toView: stackItem, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
if let percent = model.percentage {
stackItem.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: CGFloat(percent)/100.0).isActive = true
}
if lastItem {
pinView(contentView, toView: stackItem, attribute: .right, relation: .equal, priority: .required, constant: 0)
}
}
if lastItem {
pinView(contentView, toView: view, attribute: .right, relation: .equal, priority: .required, constant: 0)
}
items.append(stackItem)
}
func setWithStackItems(_ items: [StackItemModel]) {
removeAllItemViews()
self.items.removeAll()
var previousPresentItem: StackItemModel? = nil
for item in items {
if !item.gone {
previousPresentItem = item
}
addStackItem(item, lastItem: false)
}
if let lastView = previousPresentItem?.view {
let attribute: NSLayoutConstraint.Attribute = axis == .vertical ? .bottom : .right
pinView(contentView, toView: lastView, attribute: attribute, relation: .equal, priority: .required, constant: 0)
}
stackItems.append(stackItem)
}
}

View File

@ -67,7 +67,8 @@
@"tabsListItem": TabsTableViewCell.class,
@"dropDownListItem": DropDownFilterTableViewCell.class,
@"headlineBodyButton": HeadlineBodyButton.class,
@"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class
@"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class,
@"stackItem": StackItem.class
} mutableCopy];
});
return mapping;

View File

@ -18,7 +18,6 @@ import Foundation
ModelRegistry.register(ListItemModel.self)
ModelRegistry.register(TextFieldModel.self)
ModelRegistry.register(LineModel.self)
ModelRegistry.register(SeperatorModel.self)
ModelRegistry.register(ProgressBarModel.self)
ModelRegistry.register(MultiProgressBarModel.self)
ModelRegistry.register(CaretViewModel.self)