container protocol updates and container model

This commit is contained in:
Pfeil, Scott Robert 2020-04-23 15:13:29 -04:00
parent f7406c0bf9
commit d3a73939f0
19 changed files with 129 additions and 128 deletions

View File

@ -120,6 +120,7 @@ import Foundation
// Other Container Molecules
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeContainer.self, viewModelClass: MoleculeContainerModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeHeaderView.self, viewModelClass: MoleculeHeaderModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self)

View File

@ -25,8 +25,8 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
public override func setDefaults() {
super.setDefaults()
topMarginPadding = PaddingDefaultVerticalSpacing3
bottomMarginPadding = PaddingDefaultVerticalSpacing3
topPadding = PaddingDefaultVerticalSpacing3
bottomPadding = PaddingDefaultVerticalSpacing3
}
//--------------------------------------------------

View File

@ -9,47 +9,24 @@
import Foundation
@objcMembers public class FooterModel: MoleculeContainerModel, MoleculeModelProtocol {
public static var identifier: String = "footer"
public var backgroundColor: Color?
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
@objcMembers public class FooterModel: MoleculeContainerModel {
public override class var identifier: String {
return "footer"
}
/// Defaults to set
func setDefaults() {
public override func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
if useVerticalMargins == nil {
useVerticalMargins = true
}
if topMarginPadding == nil {
topMarginPadding = PaddingDefaultVerticalSpacing
if topPadding == nil {
topPadding = PaddingDefaultVerticalSpacing
}
if bottomMarginPadding == nil {
bottomMarginPadding = PaddingDefaultVerticalSpacing
if bottomPadding == nil {
bottomPadding = PaddingDefaultVerticalSpacing
}
}
public override init(with moleculeModel: MoleculeModelProtocol) {
super.init(with: moleculeModel)
setDefaults()
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder)
setDefaults()
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
}
}

View File

@ -18,18 +18,18 @@ import Foundation
}
/// Defaults to set
public func setDefaults() {
public override func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
if useVerticalMargins == nil {
useVerticalMargins = true
}
if topMarginPadding == nil {
topMarginPadding = PaddingDefaultVerticalSpacing
if topPadding == nil {
topPadding = PaddingDefaultVerticalSpacing
}
if bottomMarginPadding == nil {
bottomMarginPadding = PaddingDefaultVerticalSpacing
if bottomPadding == nil {
bottomPadding = PaddingDefaultVerticalSpacing
}
if line == nil {
line = LineModel(type: .heavy)
@ -38,7 +38,6 @@ import Foundation
public override init() {
super.init()
setDefaults()
}
required public init(from decoder: Decoder) throws {
@ -46,7 +45,6 @@ import Foundation
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
setDefaults()
}
public override func encode(to encoder: Encoder) throws {

View File

@ -38,7 +38,7 @@ import Foundation
//--------------------------------------------------
/// Defaults to set
open func setDefaults() {
open override func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
@ -54,9 +54,12 @@ import Foundation
// MARK: - Initializer
//--------------------------------------------------
public override init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, useHorizontalMargins: Bool? = nil, leftPadding: CGFloat? = nil, rightPadding: CGFloat? = nil, useVerticalMargins: Bool? = nil, topPadding: CGFloat? = nil, bottomPadding: CGFloat? = nil) {
super.init(horizontalAlignment: horizontalAlignment, verticalAlignment: verticalAlignment, useHorizontalMargins: useHorizontalMargins, leftPadding: leftPadding, rightPadding: rightPadding, useVerticalMargins: useVerticalMargins, topPadding: topPadding, bottomPadding: bottomPadding)
}
public override init() {
super.init()
setDefaults()
}
//--------------------------------------------------
@ -71,7 +74,6 @@ import Foundation
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
style = try typeContainer.decodeIfPresent(String.self, forKey: .style)
try super.init(from: decoder)
setDefaults()
}
open override func encode(to encoder: Encoder) throws {

View File

@ -9,49 +9,36 @@
import Foundation
/// A model for a collection item that is a container for any molecule.
@objcMembers public class MoleculeCollectionItemModel: MoleculeContainerModel, CollectionItemModelProtocol, MoleculeModelProtocol {
open class var identifier: String {
@objcMembers public class MoleculeCollectionItemModel: MoleculeContainerModel, CollectionItemModelProtocol {
open override class var identifier: String {
return "collectionItem"
}
public var backgroundColor: Color?
/// Defaults to set
public func setDefaults() {
public override func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
if useVerticalMargins == nil {
useVerticalMargins = true
}
if topMarginPadding == nil {
topMarginPadding = PaddingDefault
if topPadding == nil {
topPadding = PaddingDefault
}
if bottomMarginPadding == nil {
bottomMarginPadding = PaddingDefault
if bottomPadding == nil {
bottomPadding = PaddingDefault
}
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
}
public override init(with moleculeModel: MoleculeModelProtocol) {
super.init(with: moleculeModel)
setDefaults()
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder)
setDefaults()
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
}
}

View File

@ -54,6 +54,6 @@ open class MoleculeCollectionViewCell: CollectionViewCell {
let height = classType.estimatedHeight(with: model.molecule, delegateObject)
else { return 100 }
return height + (model.topMarginPadding ?? 0) + (model.bottomMarginPadding ?? 0)
return height + (model.topPadding ?? 0) + (model.bottomPadding ?? 0)
}
}

View File

@ -8,16 +8,15 @@
import Foundation
@objcMembers public class MoleculeStackItemModel: MoleculeContainerModel, MoleculeModelProtocol, StackItemModelProtocol {
public static var identifier: String = "stackItem"
public var backgroundColor: Color?
@objcMembers public class MoleculeStackItemModel: MoleculeContainerModel, StackItemModelProtocol {
public override class var identifier: String {
return "stackItem"
}
public var spacing: CGFloat?
public var percent: Int?
public var gone: Bool = false
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case spacing
case percent
case gone
@ -34,17 +33,14 @@ import Foundation
if let gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone) {
self.gone = gone
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(spacing, forKey: .spacing)
try container.encodeIfPresent(percent, forKey: .percent)
try container.encode(gone, forKey: .gone)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
}
}

View File

@ -24,16 +24,17 @@ import Foundation
// MARK: - Initializer
//--------------------------------------------------
public convenience init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) {
self.init()
self.horizontalAlignment = horizontalAlignment
self.verticalAlignment = verticalAlignment
public init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) {
self.spacing = spacing
self.percent = percent
if let gone = gone {
self.gone = gone
}
super.init(horizontalAlignment: horizontalAlignment, verticalAlignment: verticalAlignment)
}
required public init(from decoder: Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}

View File

@ -24,8 +24,8 @@ public class TabsListItemModel: ListItemModel, MoleculeModelProtocol {
hideArrow = true
action = nil
style = nil
topMarginPadding = 8
bottomMarginPadding = 0
topPadding = 8
bottomPadding = 0
}
public init(with tabs: TabsModel, molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]) {

View File

@ -8,8 +8,9 @@
import UIKit
public class ScrollerModel: MoleculeContainerModel, MoleculeModelProtocol {
public static var identifier: String = "scroller"
public class ScrollerModel: MoleculeContainerModel {
public override class var identifier: String {
return "scroller"
}
public var moleculeName: String = ScrollerModel.identifier
public var backgroundColor: Color?
}

View File

@ -20,22 +20,21 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc
self.headlineBody = headlineBody
self.image = image
super.init()
setDefaults()
}
/// Defaults to set
func setDefaults() {
public override func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
if useVerticalMargins == nil {
useVerticalMargins = true
}
if topMarginPadding == nil {
topMarginPadding = PaddingDefault
if topPadding == nil {
topPadding = PaddingDefault
}
if bottomMarginPadding == nil {
bottomMarginPadding = PaddingDefault
if bottomPadding == nil {
bottomPadding = PaddingDefault
}
if image.height == nil {
image.height = BGImageHeadlineBodyButton.heightConstant
@ -59,7 +58,6 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc
image = try typeContainer.decode(ImageViewModel.self, forKey: .image)
button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button)
try super.init(from: decoder)
setDefaults()
}
public override func encode(to encoder: Encoder) throws {

View File

@ -19,22 +19,21 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto
self.headlineBody = headlineBody
self.image = image
super.init()
setDefaults()
}
/// Defaults to set
func setDefaults() {
public override func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
if useVerticalMargins == nil {
useVerticalMargins = true
}
if topMarginPadding == nil {
topMarginPadding = PaddingDefault
if topPadding == nil {
topPadding = PaddingDefault
}
if bottomMarginPadding == nil {
bottomMarginPadding = PaddingDefault
if bottomPadding == nil {
bottomPadding = PaddingDefault
}
if image.height == nil {
image.height = HeadLineBodyCaretLinkImage.heightConstant
@ -56,7 +55,6 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto
image = try typeContainer.decode(ImageViewModel.self, forKey: .image)
caretLink = try typeContainer.decodeIfPresent(CaretLinkModel.self, forKey: .caretLink)
try super.init(from: decoder)
setDefaults()
}
public override func encode(to encoder: Encoder) throws {

View File

@ -11,10 +11,12 @@ import Foundation
public protocol ContainerModelProtocol {
var horizontalAlignment: UIStackView.Alignment? { get set }
var verticalAlignment: UIStackView.Alignment? { get set }
var useHorizontalMargins: Bool? { get set }
var leftPadding: CGFloat? { get set }
var rightPadding: CGFloat? { get set }
var verticalAlignment: UIStackView.Alignment? { get set }
var useVerticalMargins: Bool? { get set }
var topMarginPadding: CGFloat? { get set }
var bottomMarginPadding: CGFloat? { get set }
var topPadding: CGFloat? { get set }
var bottomPadding: CGFloat? { get set }
}

View File

@ -51,36 +51,36 @@ import UIKit
}
open func styleStandard() {
listItemModel?.topMarginPadding = 24
listItemModel?.bottomMarginPadding = 24
listItemModel?.topPadding = 24
listItemModel?.bottomPadding = 24
topSeparatorView?.setStyle(.none)
bottomSeparatorView?.setStyle(.standard)
}
open func styleTallDivider() {
listItemModel?.topMarginPadding = 48
listItemModel?.bottomMarginPadding = 16
listItemModel?.topPadding = 48
listItemModel?.bottomPadding = 16
topSeparatorView?.setStyle(.none)
bottomSeparatorView?.setStyle(.thin)
}
open func styleShortDivider() {
listItemModel?.topMarginPadding = 32
listItemModel?.bottomMarginPadding = 16
listItemModel?.topPadding = 32
listItemModel?.bottomPadding = 16
topSeparatorView?.setStyle(.none)
bottomSeparatorView?.setStyle(.thin)
}
open func styleFooter() {
listItemModel?.topMarginPadding = 24
listItemModel?.bottomMarginPadding = 0
listItemModel?.topPadding = 24
listItemModel?.bottomPadding = 0
topSeparatorView?.setStyle(.none)
bottomSeparatorView?.setStyle(.none)
}
open func styleNone() {
listItemModel?.topMarginPadding = 0
listItemModel?.bottomMarginPadding = 0
listItemModel?.topPadding = 0
listItemModel?.bottomPadding = 0
topSeparatorView?.setStyle(.none)
bottomSeparatorView?.setStyle(.none)
}

View File

@ -169,8 +169,15 @@ open class ContainerHelper: NSObject {
}
}
/// Updates the view margins according to model and size. If useHorizontalMargins is true, we will try to use the left and right padding, else we will default to the normal gutters. If useVerticalMargins is true, we will try to use the top and bottom padding. All else, we use zero.
open 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)
let left = (model?.useHorizontalMargins ?? false) ? (model?.leftPadding ?? Padding.Component.horizontalPaddingForSize(size)) : 0.0
let right = (model?.useHorizontalMargins ?? false) ? (model?.rightPadding ?? Padding.Component.horizontalPaddingForSize(size)) : 0.0
let top = (model?.useVerticalMargins ?? false) ? (model?.topPadding ?? 0.0) : 0.0
let bottom = (model?.useVerticalMargins ?? false) ? (model?.bottomPadding ?? 0.0) : 0.0
MVMCoreDispatchUtility.performBlock(onMainThread: {
MVMCoreUIUtility.setMarginsFor(view, leading: left, top: top, trailing: right, bottom: bottom)
})
}
open func set(with model: ContainerModelProtocol, for contained: MVMCoreUIViewConstrainingProtocol?) {

View File

@ -9,41 +9,61 @@
import Foundation
open class ContainerModel: ContainerModelProtocol, Codable {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var horizontalAlignment: UIStackView.Alignment?
public var verticalAlignment: UIStackView.Alignment?
public var useHorizontalMargins: Bool?
public var leftPadding: CGFloat?
public var rightPadding: CGFloat?
public var verticalAlignment: UIStackView.Alignment?
public var useVerticalMargins: Bool?
public var topMarginPadding: CGFloat?
public var bottomMarginPadding: CGFloat?
public var topPadding: CGFloat?
public var bottomPadding: CGFloat?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case verticalAlignment
case horizontalAlignment
case useHorizontalMargins
case leftPadding
case rightPadding
case verticalAlignment
case useVerticalMargins
case topMarginPadding
case bottomMarginPadding
case topPadding
case bottomPadding
}
//--------------------------------------------------
// MARK: - Subclassable
//--------------------------------------------------
/// Sets the default values. Should be called on init.
public func setDefaults() {}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public init() {}
public init() {
setDefaults()
}
public convenience init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil) {
self.init()
public init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, useHorizontalMargins: Bool? = nil, leftPadding: CGFloat? = nil, rightPadding: CGFloat? = nil, useVerticalMargins: Bool? = nil, topPadding: CGFloat? = nil, bottomPadding: CGFloat? = nil) {
self.horizontalAlignment = horizontalAlignment
self.verticalAlignment = verticalAlignment
self.useHorizontalMargins = useHorizontalMargins
self.leftPadding = leftPadding
self.rightPadding = rightPadding
self.useVerticalMargins = useVerticalMargins
self.topPadding = topPadding
self.bottomPadding = bottomPadding
setDefaults()
}
//--------------------------------------------------
@ -59,9 +79,12 @@ open class ContainerModel: ContainerModelProtocol, Codable {
horizontalAlignment = ContainerHelper.getAlignment(for: horizontalAlignmentString)
}
useHorizontalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useHorizontalMargins)
leftPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .leftPadding)
rightPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .rightPadding)
useVerticalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalMargins)
topMarginPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .topMarginPadding)
bottomMarginPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .bottomMarginPadding)
topPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .topPadding)
bottomPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .bottomPadding)
setDefaults()
}
open func encode(to encoder: Encoder) throws {
@ -69,9 +92,10 @@ open class ContainerModel: ContainerModelProtocol, Codable {
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(leftPadding, forKey: .leftPadding)
try container.encodeIfPresent(rightPadding, forKey: .rightPadding)
try container.encodeIfPresent(useVerticalMargins, forKey: .useVerticalMargins)
// TODO: can add this back once we have type erasures.
//try container.encodeIfPresent(topMarginPadding, forKey: .topMarginPadding)
//try container.encodeIfPresent(bottomMarginPadding, forKey: .bottomMarginPadding)
try container.encodeIfPresent(topPadding, forKey: .topPadding)
try container.encodeIfPresent(bottomPadding, forKey: .bottomPadding)
}
}

View File

@ -41,9 +41,9 @@ open class MoleculeContainer: Container {
guard let containerModel = model as? MoleculeContainerModelProtocol else { return 0 }
guard let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(containerModel.molecule),
let moleculeHeight = moleculeClass.estimatedHeight(with: containerModel.molecule, delegateObject) else {
return (containerModel.topMarginPadding ?? 0) + (containerModel.bottomMarginPadding ?? 0)
return (containerModel.topPadding ?? 0) + (containerModel.bottomPadding ?? 0)
}
return moleculeHeight + (containerModel.topMarginPadding ?? 0) + (containerModel.bottomMarginPadding ?? 0)
return moleculeHeight + (containerModel.topPadding ?? 0) + (containerModel.bottomPadding ?? 0)
}
public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {

View File

@ -8,11 +8,17 @@
import Foundation
public class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol {
public class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol, MoleculeModelProtocol {
public class var identifier: String {
return "container"
}
public var backgroundColor: Color?
public var molecule: MoleculeModelProtocol
private enum CodingKeys: String, CodingKey {
case moleculeName
case molecule
case backgroundColor
}
public init(with moleculeModel: MoleculeModelProtocol) {
@ -23,12 +29,15 @@ public class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProto
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecule = try typeContainer.decodeModel(codingKey: .molecule)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModel(molecule, forKey: .molecule)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
}
}