Merge branch 'feature/code_condensing' into 'develop'
Feature/code condensing See merge request BPHV_MIPS/mvm_core_ui!274
This commit is contained in:
commit
a132a51903
@ -24,7 +24,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol {
|
|||||||
public var title: String
|
public var title: String
|
||||||
public var action: ActionModelProtocol
|
public var action: ActionModelProtocol
|
||||||
public var enabled: Bool = true
|
public var enabled: Bool = true
|
||||||
public var style: ButtonStyle?
|
public var style: ButtonStyle? = .primary
|
||||||
public var size: ButtonSize? = .standard
|
public var size: ButtonSize? = .standard
|
||||||
public var fillColor: Color?
|
public var fillColor: Color?
|
||||||
public var textColor: Color?
|
public var textColor: Color?
|
||||||
|
|||||||
@ -15,7 +15,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol {
|
|||||||
public var title: String
|
public var title: String
|
||||||
public var action: ActionModelProtocol
|
public var action: ActionModelProtocol
|
||||||
public var enabledColor: Color = Color(uiColor: .black)
|
public var enabledColor: Color = Color(uiColor: .black)
|
||||||
public var disabledColor: Color? = Color(uiColor: .mfSilver())
|
public var disabledColor: Color? = Color(uiColor: .mvmCoolGray6)
|
||||||
public var enabled = true
|
public var enabled = true
|
||||||
|
|
||||||
public init(title: String, action: ActionModelProtocol) {
|
public init(title: String, action: ActionModelProtocol) {
|
||||||
|
|||||||
@ -58,6 +58,8 @@ import Foundation
|
|||||||
case isEnabled
|
case isEnabled
|
||||||
case action
|
case action
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init(isChecked: Bool = false) {}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Codec
|
// MARK: - Codec
|
||||||
|
|||||||
@ -37,7 +37,10 @@ public class CircleProgressModel: MoleculeModelProtocol {
|
|||||||
public var colors = [Color]()
|
public var colors = [Color]()
|
||||||
public var backgroundColor: Color?
|
public var backgroundColor: Color?
|
||||||
|
|
||||||
public init() {}
|
public init() {
|
||||||
|
updateStyle()
|
||||||
|
updateSize()
|
||||||
|
}
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case style
|
case style
|
||||||
|
|||||||
@ -231,6 +231,7 @@ public typealias ActionBlock = () -> ()
|
|||||||
attributedText = nil
|
attributedText = nil
|
||||||
originalAttributedString = nil
|
originalAttributedString = nil
|
||||||
text = labelModel.text
|
text = labelModel.text
|
||||||
|
hero = labelModel.hero
|
||||||
Label.setLabel(self, withHTML: labelModel.html)
|
Label.setLabel(self, withHTML: labelModel.html)
|
||||||
|
|
||||||
let alignment = LabelAlignment(rawValue: labelModel.textAlignment ?? "")
|
let alignment = LabelAlignment(rawValue: labelModel.textAlignment ?? "")
|
||||||
@ -344,7 +345,6 @@ public typealias ActionBlock = () -> ()
|
|||||||
}
|
}
|
||||||
attributedText = attributedString
|
attributedText = attributedString
|
||||||
originalAttributedString = attributedText
|
originalAttributedString = attributedText
|
||||||
hero = labelModel.hero
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,6 +716,7 @@ extension Label {
|
|||||||
public func reset() {
|
public func reset() {
|
||||||
text = nil
|
text = nil
|
||||||
attributedText = nil
|
attributedText = nil
|
||||||
|
hero = nil
|
||||||
textAlignment = .left
|
textAlignment = .left
|
||||||
originalAttributedString = nil
|
originalAttributedString = nil
|
||||||
styleB2(true)
|
styleB2(true)
|
||||||
@ -807,9 +808,6 @@ extension Label {
|
|||||||
|
|
||||||
- Attention: This method expects text to be set first. Otherwise, it will do nothing.
|
- Attention: This method expects text to be set first. Otherwise, it will do nothing.
|
||||||
- parameter range: The range of text to be tapped.
|
- parameter range: The range of text to be tapped.
|
||||||
- parameter actionMap:
|
|
||||||
- parameter delegate:
|
|
||||||
- parameter additionalData:
|
|
||||||
*/
|
*/
|
||||||
@objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
@objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,10 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@objcMembers public class LabelModel: MoleculeModelProtocol {
|
@objcMembers public class LabelModel: MoleculeModelProtocol {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
public static var identifier: String = "label"
|
public static var identifier: String = "label"
|
||||||
public var backgroundColor: Color?
|
public var backgroundColor: Color?
|
||||||
public var text: String
|
public var text: String
|
||||||
@ -24,6 +28,10 @@ import Foundation
|
|||||||
public var hero: Int?
|
public var hero: Int?
|
||||||
public var makeWholeViewClickable: Bool?
|
public var makeWholeViewClickable: Bool?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Keys
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case moleculeName
|
case moleculeName
|
||||||
case text
|
case text
|
||||||
@ -43,11 +51,19 @@ import Foundation
|
|||||||
enum AttributeTypeKey: String, CodingKey {
|
enum AttributeTypeKey: String, CodingKey {
|
||||||
case type
|
case type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializer
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
public init(text: String) {
|
public init(text: String) {
|
||||||
self.text = text
|
self.text = text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Codec
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
text = try typeContainer.decode(String.self, forKey: .text)
|
text = try typeContainer.decode(String.self, forKey: .text)
|
||||||
|
|||||||
@ -139,7 +139,6 @@ import UIKit
|
|||||||
|
|
||||||
topSeparatorView?.updateView(size)
|
topSeparatorView?.updateView(size)
|
||||||
bottomSeparatorView?.updateView(size)
|
bottomSeparatorView?.updateView(size)
|
||||||
|
|
||||||
molecule?.updateView(size)
|
molecule?.updateView(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,9 +152,7 @@ import UIKit
|
|||||||
|
|
||||||
//TODO: Model, Change to model
|
//TODO: Model, Change to model
|
||||||
public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
guard let model = model as? ListItemModelProtocol else {
|
guard let model = model as? ListItemModelProtocol else { return }
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.listItemModel = model
|
self.listItemModel = model
|
||||||
style(with: model.style)
|
style(with: model.style)
|
||||||
@ -194,20 +191,21 @@ import UIKit
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Arrow
|
// MARK: - Caret View
|
||||||
/// Adds the standard mvm style caret to the accessory view
|
/// Adds the standard mvm style caret to the accessory view
|
||||||
@objc public func addCaretViewAccessory() {
|
@objc public func addCaretViewAccessory() {
|
||||||
guard accessoryView == nil else { return }
|
guard accessoryView == nil else { return }
|
||||||
caretView = CaretView(lineWidth: 1)
|
|
||||||
caretView?.translatesAutoresizingMaskIntoConstraints = true
|
|
||||||
caretView?.size = .small(.vertical)
|
|
||||||
caretView?.setConstraints()
|
|
||||||
|
|
||||||
if let size = caretView?.size?.dimensions() {
|
let caret = CaretView(lineWidth: 1)
|
||||||
|
caret.translatesAutoresizingMaskIntoConstraints = true
|
||||||
|
caret.size = .small(.vertical)
|
||||||
|
if let size = caret.size?.dimensions() {
|
||||||
|
caret.frame = CGRect(origin: CGPoint.zero, size: size)
|
||||||
caretViewWidthSizeObject = MFSizeObject(standardSize: size.width, standardiPadPortraitSize: 9)
|
caretViewWidthSizeObject = MFSizeObject(standardSize: size.width, standardiPadPortraitSize: 9)
|
||||||
caretViewHeightSizeObject = MFSizeObject(standardSize: size.height, standardiPadPortraitSize: 16)
|
caretViewHeightSizeObject = MFSizeObject(standardSize: size.height, standardiPadPortraitSize: 16)
|
||||||
}
|
}
|
||||||
accessoryView = caretView
|
caretView = caret
|
||||||
|
accessoryView = caret
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NOTE: Should only be called when displayed or about to be displayed.
|
/// NOTE: Should only be called when displayed or about to be displayed.
|
||||||
@ -217,11 +215,11 @@ import UIKit
|
|||||||
layoutIfNeeded()
|
layoutIfNeeded()
|
||||||
guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return }
|
guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return }
|
||||||
let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel)
|
let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel)
|
||||||
accessoryView?.center.y = contentView.convert(UIView(frame: rect).center, from: heroLabel).y
|
accessoryView?.center.y = convert(UIView(frame: rect).center, from: heroLabel).y
|
||||||
heroAccessoryCenter = accessoryView?.center
|
heroAccessoryCenter = accessoryView?.center
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverses the view hierarchy for a 🦸♂️heroic Label.
|
/// Traverses the view hierarchy for a 🦸♂️ heroic Label.
|
||||||
private func findHeroLabel(views: [UIView]) -> Label? {
|
private func findHeroLabel(views: [UIView]) -> Label? {
|
||||||
|
|
||||||
if views.isEmpty {
|
if views.isEmpty {
|
||||||
|
|||||||
@ -27,6 +27,12 @@ public class ContainerModel: ContainerModelProtocol, Codable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public init() {}
|
public init() {}
|
||||||
|
|
||||||
|
public convenience init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil) {
|
||||||
|
self.init()
|
||||||
|
self.horizontalAlignment = horizontalAlignment
|
||||||
|
self.verticalAlignment = verticalAlignment
|
||||||
|
}
|
||||||
|
|
||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|||||||
@ -8,49 +8,33 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@objcMembers public class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell {
|
@objcMembers open class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell {
|
||||||
public let checkbox = Checkbox(frame: .zero)
|
public let checkbox = Checkbox(frame: .zero)
|
||||||
public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero)
|
public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero)
|
||||||
public let stack = Stack<StackModel>(frame: .zero)
|
public let stack = Stack<StackModel>(frame: .zero)
|
||||||
|
|
||||||
// MARK: - View Lifecycle
|
// MARK: - View Lifecycle
|
||||||
open override func updateView(_ size: CGFloat) {
|
|
||||||
super.updateView(size)
|
|
||||||
stack.updateView(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
override open func setupView() {
|
override open func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
stack.stackItems = [StackItem(andContain: checkbox),StackItem(andContain: eyebrowHeadlineBodyLink)]
|
stack.stackItems = [StackItem(andContain: checkbox),StackItem(andContain: eyebrowHeadlineBodyLink)]
|
||||||
contentView.addSubview(stack)
|
addMolecule(stack)
|
||||||
containerHelper.constrainView(stack)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK:- ModelMoleculeViewProtocol
|
|
||||||
override open func reset() {
|
|
||||||
super.reset()
|
|
||||||
stack.reset()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK:- MVMCoreUIMoleculeViewProtocol
|
// MARK:- MVMCoreUIMoleculeViewProtocol
|
||||||
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||||
super.setWithModel(model, delegateObject, additionalData)
|
super.setWithModel(model, delegateObject, additionalData)
|
||||||
guard let model = model as? ListLeftVariableCheckboxAllTextAndLinksModel else { return}
|
guard let model = model as? ListLeftVariableCheckboxAllTextAndLinksModel else { return}
|
||||||
checkbox.setWithModel(model.checkbox, delegateObject, additionalData)
|
checkbox.setWithModel(model.checkbox, delegateObject, additionalData)
|
||||||
eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData)
|
eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData)
|
||||||
|
|
||||||
// Create a stack model to use for the internal stack and set the alignment of labels
|
let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill),
|
||||||
let checkbox = StackItemModel()
|
StackItemModel(horizontalAlignment: .leading)],
|
||||||
checkbox.horizontalAlignment = .fill
|
axis: .horizontal)
|
||||||
let eyebrowHeadlineBodyLink = StackItemModel()
|
|
||||||
eyebrowHeadlineBodyLink.horizontalAlignment = .leading
|
|
||||||
let stackModel = StackModel(molecules: [checkbox,eyebrowHeadlineBodyLink])
|
|
||||||
stackModel.axis = .horizontal
|
|
||||||
stack.model = stackModel
|
stack.model = stackModel
|
||||||
stack.restack()
|
stack.restack()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 140
|
return 140
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ public class ListLeftVariableCheckboxAllTextAndLinksModel: ListItemModel, Molecu
|
|||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink)
|
eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink)
|
||||||
checkbox = try typeContainer.decode(CheckboxModel.self, forKey: .checkbox)
|
checkbox = try typeContainer.decodeIfPresent(CheckboxModel.self, forKey: .checkbox) ?? CheckboxModel()
|
||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
@objcMembers public class ListLeftVariableIconWithRightCaret: TableViewCell {
|
@objcMembers open class ListLeftVariableIconWithRightCaret: TableViewCell {
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
// MARK: - Outlets
|
// MARK: - Outlets
|
||||||
@ -22,17 +22,11 @@ import UIKit
|
|||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
// MARK: - View Lifecycle
|
// MARK: - View Lifecycle
|
||||||
//-------------------------------------------------------
|
//-------------------------------------------------------
|
||||||
open override func updateView(_ size: CGFloat) {
|
|
||||||
super.updateView(size)
|
|
||||||
stack.updateView(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
override open func setupView() {
|
override open func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
stack.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
stack.stackItems = [StackItem(andContain: leftImage),StackItem(andContain: leftLabel),StackItem(andContain: rightLabel)]
|
stack.stackItems = [StackItem(andContain: leftImage),StackItem(andContain: leftLabel),StackItem(andContain: rightLabel)]
|
||||||
contentView.addSubview(stack)
|
addMolecule(stack)
|
||||||
containerHelper.constrainView(stack)
|
|
||||||
leftLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal)
|
leftLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal)
|
||||||
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal)
|
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal)
|
||||||
}
|
}
|
||||||
@ -40,32 +34,28 @@ import UIKit
|
|||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
// MARK: - Molecule
|
// MARK: - Molecule
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
override open func reset() {
|
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||||
super.reset()
|
|
||||||
stack.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
|
||||||
super.setWithModel(model, delegateObject, additionalData)
|
super.setWithModel(model, delegateObject, additionalData)
|
||||||
guard let model = model as? ListLeftVariableIconWithRightCaretModel else { return}
|
guard let model = model as? ListLeftVariableIconWithRightCaretModel else { return}
|
||||||
leftImage.setWithModel(model.image, delegateObject, additionalData)
|
leftImage.setWithModel(model.image, delegateObject, additionalData)
|
||||||
leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData)
|
leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData)
|
||||||
rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData)
|
rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData)
|
||||||
|
|
||||||
// Create a stack model to use for the internal stack and set the alignment of labels
|
let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill),
|
||||||
let leftImage = StackItemModel()
|
StackItemModel(horizontalAlignment: .fill),
|
||||||
leftImage.horizontalAlignment = .fill
|
StackItemModel(horizontalAlignment: .trailing)],
|
||||||
let leftLabel = StackItemModel()
|
axis: .horizontal)
|
||||||
leftLabel.horizontalAlignment = .fill
|
|
||||||
let rightLabel = StackItemModel()
|
|
||||||
rightLabel.horizontalAlignment = .trailing
|
|
||||||
let stackModel = StackModel(molecules: [leftImage,leftLabel,rightLabel])
|
|
||||||
stackModel.axis = .horizontal
|
|
||||||
stack.model = stackModel
|
stack.model = stackModel
|
||||||
stack.restack()
|
stack.restack()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 90
|
return 90
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func reset() {
|
||||||
|
super.reset()
|
||||||
|
leftLabel.styleB2(true)
|
||||||
|
rightLabel.styleB2(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ public class ListLeftVariableIconWithRightCaretModel: ListItemModel, MoleculeMod
|
|||||||
if image.height == nil {
|
if image.height == nil {
|
||||||
image.height = 30.0
|
image.height = 30.0
|
||||||
}
|
}
|
||||||
|
rightLabel.hero = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(image: ImageViewModel, leftLabel: LabelModel, rightLabel: LabelModel) {
|
public init(image: ImageViewModel, leftLabel: LabelModel, rightLabel: LabelModel) {
|
||||||
@ -43,7 +44,7 @@ public class ListLeftVariableIconWithRightCaretModel: ListItemModel, MoleculeMod
|
|||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func encode(to encoder: Encoder) throws {
|
public override func encode(to encoder: Encoder) throws {
|
||||||
try super.encode(to: encoder)
|
try super.encode(to: encoder)
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
|
|||||||
@ -13,46 +13,30 @@ import Foundation
|
|||||||
let rightLabel = Label.commonLabelB2(true)
|
let rightLabel = Label.commonLabelB2(true)
|
||||||
let stack = Stack<StackModel>(frame: .zero)
|
let stack = Stack<StackModel>(frame: .zero)
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// MARK: - View Cycle
|
|
||||||
//-------------------------------------------------
|
|
||||||
open override func updateView(_ size: CGFloat) {
|
|
||||||
super.updateView(size)
|
|
||||||
stack.updateView(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// MARK: - Setup
|
// MARK: - Setup
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
open override func setupView() {
|
open override func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||||
stack.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: wheel),StackItem(andContain: rightLabel)]
|
stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: wheel),StackItem(andContain: rightLabel)]
|
||||||
contentView.addSubview(stack)
|
addMolecule(stack)
|
||||||
containerHelper.constrainView(stack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// MARK: - ModelMoleculeViewProtocol
|
// MARK: - ModelMoleculeViewProtocol
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||||
super.setWithModel(model, delegateObject, additionalData)
|
super.setWithModel(model, delegateObject, additionalData)
|
||||||
guard let model = model as? ListRVWheelModel else { return }
|
guard let model = model as? ListRVWheelModel else { return }
|
||||||
leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData)
|
leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData)
|
||||||
rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData)
|
rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData)
|
||||||
wheel.setWithModel(model.wheel, delegateObject, additionalData)
|
wheel.setWithModel(model.wheel, delegateObject, additionalData)
|
||||||
|
|
||||||
// Create a stack model to use for the internal stack and set the alignment of models
|
let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading),
|
||||||
let leftLabelStackItem = StackItemModel()
|
StackItemModel(horizontalAlignment: .fill),
|
||||||
leftLabelStackItem.horizontalAlignment = .leading
|
StackItemModel(spacing: 4, horizontalAlignment: .fill)],
|
||||||
let wheelStackItem = StackItemModel()
|
axis: .horizontal)
|
||||||
wheelStackItem.horizontalAlignment = .fill
|
|
||||||
let rightLabelStackItem = StackItemModel()
|
|
||||||
rightLabelStackItem.horizontalAlignment = .fill
|
|
||||||
rightLabelStackItem.spacing = 4
|
|
||||||
let stackModel = StackModel(molecules: [leftLabelStackItem,wheelStackItem,rightLabelStackItem])
|
|
||||||
stackModel.axis = .horizontal
|
|
||||||
stack.model = stackModel
|
stack.model = stackModel
|
||||||
stack.restack()
|
stack.restack()
|
||||||
}
|
}
|
||||||
@ -62,7 +46,6 @@ import Foundation
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
stack.reset()
|
|
||||||
leftLabel.styleB1(true)
|
leftLabel.styleB1(true)
|
||||||
rightLabel.styleB2(true)
|
rightLabel.styleB2(true)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,12 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol {
|
|||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defaults to set
|
||||||
|
override public func setDefaults() {
|
||||||
|
super.setDefaults()
|
||||||
|
rightLabel.hero = 0
|
||||||
|
}
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case moleculeName
|
case moleculeName
|
||||||
case leftLabel
|
case leftLabel
|
||||||
@ -31,7 +37,7 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol {
|
|||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
|
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
|
||||||
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
||||||
wheel = try typeContainer.decode(CircleProgressModel.self, forKey: .wheel)
|
wheel = try typeContainer.decodeIfPresent(CircleProgressModel.self, forKey: .wheel) ?? CircleProgressModel()
|
||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,12 +8,11 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@objcMembers public class ListRightVariablePayments: TableViewCell {
|
@objcMembers open class ListRightVariablePayments: TableViewCell {
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
// MARK: - Outlets
|
// MARK: - Outlets
|
||||||
//-------------------------------------------------------
|
//-------------------------------------------------------
|
||||||
|
|
||||||
let leftLabel = Label.commonLabelB1(true)
|
let leftLabel = Label.commonLabelB1(true)
|
||||||
let rightImage = MFLoadImageView(pinnedEdges: .all)
|
let rightImage = MFLoadImageView(pinnedEdges: .all)
|
||||||
let stack = Stack<StackModel>(frame: .zero)
|
let stack = Stack<StackModel>(frame: .zero)
|
||||||
@ -21,49 +20,34 @@ import Foundation
|
|||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
// MARK: - View Lifecycle
|
// MARK: - View Lifecycle
|
||||||
//-------------------------------------------------------
|
//-------------------------------------------------------
|
||||||
|
|
||||||
open override func updateView(_ size: CGFloat) {
|
|
||||||
super.updateView(size)
|
|
||||||
stack.updateView(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
override open func setupView() {
|
override open func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
guard leftLabel.superview == nil else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
stack.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)]
|
stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)]
|
||||||
contentView.addSubview(stack)
|
addMolecule(stack)
|
||||||
containerHelper.constrainView(stack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
// MARK: - Molecule
|
// MARK: - Molecule
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
override open func reset() {
|
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||||
super.reset()
|
|
||||||
stack.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
|
||||||
super.setWithModel(model, delegateObject, additionalData)
|
super.setWithModel(model, delegateObject, additionalData)
|
||||||
guard let model = model as? ListRightVariablePaymentsModel else { return }
|
guard let model = model as? ListRightVariablePaymentsModel else { return }
|
||||||
leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData)
|
leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData)
|
||||||
rightImage.setWithModel(model.image, delegateObject, additionalData)
|
rightImage.setWithModel(model.image, delegateObject, additionalData)
|
||||||
|
|
||||||
// Create a stack model to use for the internal stack and set the alignment of label and image
|
let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading),
|
||||||
let leftLabel = StackItemModel()
|
StackItemModel(horizontalAlignment: .fill)],
|
||||||
leftLabel.horizontalAlignment = .leading
|
axis: .horizontal)
|
||||||
let rightImage = StackItemModel()
|
|
||||||
rightImage.horizontalAlignment = .fill
|
|
||||||
let stackModel = StackModel(molecules: [leftLabel,rightImage])
|
|
||||||
stackModel.axis = .horizontal
|
|
||||||
stack.model = stackModel
|
stack.model = stackModel
|
||||||
stack.restack()
|
stack.restack()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 65
|
return 65
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func reset() {
|
||||||
|
super.reset()
|
||||||
|
leftLabel.styleB1(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,12 @@ public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtoco
|
|||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defaults to set
|
||||||
|
override public func setDefaults() {
|
||||||
|
super.setDefaults()
|
||||||
|
leftLabel.hero = 0
|
||||||
|
}
|
||||||
|
|
||||||
static func createPayPalImage() -> ImageViewModel {
|
static func createPayPalImage() -> ImageViewModel {
|
||||||
let image = ImageViewModel(image: "imageName_PayPal_logo")
|
let image = ImageViewModel(image: "imageName_PayPal_logo")
|
||||||
image.localBundle = MVMCoreUIUtility.bundleForMVMCoreUI()
|
image.localBundle = MVMCoreUIUtility.bundleForMVMCoreUI()
|
||||||
|
|||||||
@ -16,23 +16,16 @@ import Foundation
|
|||||||
let stack = Stack<StackModel>(frame: .zero)
|
let stack = Stack<StackModel>(frame: .zero)
|
||||||
|
|
||||||
// MARK: - MFViewProtocol
|
// MARK: - MFViewProtocol
|
||||||
open override func updateView(_ size: CGFloat) {
|
|
||||||
super.updateView(size)
|
|
||||||
stack.updateView(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
open override func setupView() {
|
open override func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
|
|
||||||
//using stackItems to align the three headlineBody
|
//using stackItems to align the three headlineBody
|
||||||
stack.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
stack.stackItems = [StackItem(andContain: leftHeadlineBody),StackItem(andContain: centerHeadLineBody),StackItem(andContain: rightHeadLineBody)]
|
stack.stackItems = [StackItem(andContain: leftHeadlineBody),StackItem(andContain: centerHeadLineBody),StackItem(andContain: rightHeadLineBody)]
|
||||||
contentView.addSubview(stack)
|
addMolecule(stack)
|
||||||
containerHelper.constrainView(stack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||||
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||||
super.setWithModel(model, delegateObject, additionalData)
|
super.setWithModel(model, delegateObject, additionalData)
|
||||||
guard let model = model as? ListThreeColumnPlanDataDividerModel else { return }
|
guard let model = model as? ListThreeColumnPlanDataDividerModel else { return }
|
||||||
leftHeadlineBody.setWithModel(model.leftHeadlineBody, delegateObject, additionalData)
|
leftHeadlineBody.setWithModel(model.leftHeadlineBody, delegateObject, additionalData)
|
||||||
@ -40,24 +33,15 @@ import Foundation
|
|||||||
rightHeadLineBody.setWithModel(model.rightHeadlineBody, delegateObject, additionalData)
|
rightHeadLineBody.setWithModel(model.rightHeadlineBody, delegateObject, additionalData)
|
||||||
|
|
||||||
// Create a stack model to use for the internal stack and set the alignment of models
|
// Create a stack model to use for the internal stack and set the alignment of models
|
||||||
let leftHeadlineBodyAlignment = StackItemModel(percent: 33)
|
let stackModel = StackModel(molecules: [StackItemModel(percent: 33, horizontalAlignment: .leading),
|
||||||
leftHeadlineBodyAlignment.horizontalAlignment = .leading
|
StackItemModel(percent: 34, horizontalAlignment: .center),
|
||||||
let centerHeadLineBodyAlignment = StackItemModel(percent: 34)
|
StackItemModel(percent: 33, horizontalAlignment: .trailing)],
|
||||||
centerHeadLineBodyAlignment.horizontalAlignment = .center
|
axis: .horizontal)
|
||||||
let rightHeadLineBodyAlignment = StackItemModel(percent: 33)
|
|
||||||
rightHeadLineBodyAlignment.horizontalAlignment = .trailing
|
|
||||||
let stackModel = StackModel(molecules: [leftHeadlineBodyAlignment,centerHeadLineBodyAlignment,rightHeadLineBodyAlignment])
|
|
||||||
stackModel.axis = .horizontal
|
|
||||||
stack.model = stackModel
|
stack.model = stackModel
|
||||||
stack.restack()
|
stack.restack()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func reset() {
|
open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||||
super.reset()
|
|
||||||
stack.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,9 @@ public class ListThreeColumnPlanDataDividerModel: ListItemModel, MoleculeModelPr
|
|||||||
override public func setDefaults() {
|
override public func setDefaults() {
|
||||||
super.setDefaults()
|
super.setDefaults()
|
||||||
style = "tallDivider"
|
style = "tallDivider"
|
||||||
|
leftHeadlineBody.style = "itemHeader"
|
||||||
|
centerHeadlineBody.style = "itemHeader"
|
||||||
|
rightHeadlineBody.style = "itemHeader"
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
|||||||
@ -16,13 +16,14 @@ import Foundation
|
|||||||
public var percent: Int?
|
public var percent: Int?
|
||||||
public var gone: Bool = false
|
public var gone: Bool = false
|
||||||
|
|
||||||
public convenience init(gone: Bool) {
|
public convenience init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) {
|
||||||
self.init()
|
|
||||||
self.gone = gone
|
|
||||||
}
|
|
||||||
|
|
||||||
public convenience init(percent: Int) {
|
|
||||||
self.init()
|
self.init()
|
||||||
|
self.horizontalAlignment = horizontalAlignment
|
||||||
|
self.verticalAlignment = verticalAlignment
|
||||||
|
self.spacing = spacing
|
||||||
self.percent = percent
|
self.percent = percent
|
||||||
|
if let gone = gone {
|
||||||
|
self.gone = gone
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,19 +9,30 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
@objcMembers open class EyebrowHeadlineBodyLink: Container {
|
@objcMembers open class EyebrowHeadlineBodyLink: Container {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Outlets
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
let stack = Stack<StackModel>(frame: .zero)
|
let stack = Stack<StackModel>(frame: .zero)
|
||||||
let eyebrow = Label.commonLabelB3(true)
|
let eyebrow = Label.commonLabelB3(true)
|
||||||
let headline = Label.commonLabelB1(true)
|
let headline = Label.commonLabelB1(true)
|
||||||
let body = Label.commonLabelB2(true)
|
let body = Label.commonLabelB2(true)
|
||||||
let link = Link()
|
let link = Link()
|
||||||
|
|
||||||
var casteModel: EyebrowHeadlineBodyLinkModel? {
|
var casteModel: EyebrowHeadlineBodyLinkModel? {
|
||||||
get { return model as? EyebrowHeadlineBodyLinkModel }
|
get { return model as? EyebrowHeadlineBodyLinkModel }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
// MARK: - MFViewProtocol
|
// MARK: - MFViewProtocol
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
open override func setupView() {
|
open override func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
stack.stackItems = [StackItem(andContain: eyebrow),StackItem(andContain: headline),StackItem(andContain: body),StackItem(andContain: link)]
|
stack.stackItems = [StackItem(andContain: eyebrow),
|
||||||
|
StackItem(andContain: headline),
|
||||||
|
StackItem(andContain: body),
|
||||||
|
StackItem(andContain: link)]
|
||||||
addSubview(stack)
|
addSubview(stack)
|
||||||
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
|
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
|
||||||
}
|
}
|
||||||
@ -31,7 +42,10 @@ import UIKit
|
|||||||
stack.updateView(size)
|
stack.updateView(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
stack.reset()
|
stack.reset()
|
||||||
@ -41,16 +55,23 @@ import UIKit
|
|||||||
body.styleB2(true)
|
body.styleB2(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK:- ModelMoleculeViewProtocol
|
//--------------------------------------------------
|
||||||
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
// MARK: - ModelMoleculeViewProtocol
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
super.setWithModel(model, delegateObject, additionalData)
|
super.setWithModel(model, delegateObject, additionalData)
|
||||||
|
|
||||||
eyebrow.setWithModel(casteModel?.eyebrow, delegateObject, additionalData)
|
eyebrow.setWithModel(casteModel?.eyebrow, delegateObject, additionalData)
|
||||||
headline.setWithModel(casteModel?.headline, delegateObject, additionalData)
|
headline.setWithModel(casteModel?.headline, delegateObject, additionalData)
|
||||||
body.setWithModel(casteModel?.body, delegateObject, additionalData)
|
body.setWithModel(casteModel?.body, delegateObject, additionalData)
|
||||||
link.setWithModel(casteModel?.link, delegateObject, additionalData)
|
link.setWithModel(casteModel?.link, delegateObject, additionalData)
|
||||||
|
|
||||||
// Create a stack model to use for the internal stack.
|
// Create a stack model to use for the internal stack.
|
||||||
let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText),StackItemModel(gone: !headline.hasText),StackItemModel(gone: !body.hasText),StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)])
|
let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText),
|
||||||
|
StackItemModel(gone: !headline.hasText),
|
||||||
|
StackItemModel(gone: !body.hasText),
|
||||||
|
StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)])
|
||||||
stackModel.spacing = 0
|
stackModel.spacing = 0
|
||||||
stack.model = stackModel
|
stack.model = stackModel
|
||||||
stack.restack()
|
stack.restack()
|
||||||
|
|||||||
@ -8,7 +8,11 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol {
|
public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
public static var identifier: String = "eyebrowHeadlineBodyLink"
|
public static var identifier: String = "eyebrowHeadlineBodyLink"
|
||||||
public var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier
|
public var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier
|
||||||
public var backgroundColor: Color?
|
public var backgroundColor: Color?
|
||||||
@ -16,4 +20,72 @@ public struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol {
|
|||||||
public var headline: LabelModel?
|
public var headline: LabelModel?
|
||||||
public var body: LabelModel?
|
public var body: LabelModel?
|
||||||
public var link: LinkModel?
|
public var link: LinkModel?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializer
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public init(eyebrow: LabelModel? = nil, headline: LabelModel? = nil, body: LabelModel? = nil, link: LinkModel? = nil) throws {
|
||||||
|
// TODO: This class initializers should ensure that atleast one item is set.
|
||||||
|
/*guard eyebrow != nil || headline != nil || body != nil || link != nil else {
|
||||||
|
throw
|
||||||
|
}*/
|
||||||
|
self.eyebrow = eyebrow
|
||||||
|
self.headline = headline
|
||||||
|
self.body = body
|
||||||
|
self.link = link
|
||||||
|
setDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Method
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
/// Defaults to set
|
||||||
|
public func setDefaults() {
|
||||||
|
if let headline = headline {
|
||||||
|
headline.hero = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Keys
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case moleculeName
|
||||||
|
case backgroundColor
|
||||||
|
case eyebrow
|
||||||
|
case headline
|
||||||
|
case body
|
||||||
|
case link
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Codec
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||||
|
eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow)
|
||||||
|
headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline)
|
||||||
|
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
|
||||||
|
link = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .link)
|
||||||
|
setDefaults()
|
||||||
|
// TODO: This class initializers should ensure that atleast one item is set.
|
||||||
|
/*guard eyebrow != nil || headline != nil || body != nil || link != nil else {
|
||||||
|
throw
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
|
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||||
|
try container.encodeIfPresent(eyebrow, forKey: .eyebrow)
|
||||||
|
try container.encodeIfPresent(headline, forKey: .headline)
|
||||||
|
try container.encodeIfPresent(body, forKey: .body)
|
||||||
|
try container.encodeIfPresent(link, forKey: .link)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,15 +8,24 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
open class Stack<T>: Container where T: StackModelProtocol {
|
open class Stack<T>: Container where T: StackModelProtocol {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
var contentView: UIView = MVMCoreUICommonViewsUtility.commonView()
|
var contentView: UIView = MVMCoreUICommonViewsUtility.commonView()
|
||||||
var stackModel: T? {
|
var stackModel: T? {
|
||||||
get { return model as? T }
|
get { return model as? T }
|
||||||
}
|
}
|
||||||
var stackItems: [UIView] = []
|
var stackItems: [UIView] = []
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
// MARK: - Helpers
|
// MARK: - Helpers
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
public func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) {
|
public func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) {
|
||||||
|
|
||||||
let constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: relation, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant)
|
let constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: relation, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant)
|
||||||
constraint.priority = priority
|
constraint.priority = priority
|
||||||
constraint.isActive = true
|
constraint.isActive = true
|
||||||
@ -45,13 +54,16 @@ open class Stack<T>: Container where T: StackModelProtocol {
|
|||||||
item.removeFromSuperview()
|
item.removeFromSuperview()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializers
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
// MARK: - Inits
|
|
||||||
public override init(frame: CGRect) {
|
public override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
|
public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||||
super.init(frame: CGRect.zero)
|
super.init(frame: CGRect.zero)
|
||||||
setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||||
}
|
}
|
||||||
@ -60,12 +72,13 @@ open class Stack<T>: Container where T: StackModelProtocol {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
// MARK: - MFViewProtocol
|
// MARK: - MFViewProtocol
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
public override func setupView() {
|
public override func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
guard contentView.superview == nil else {
|
guard contentView.superview == nil else { return }
|
||||||
return
|
|
||||||
}
|
|
||||||
MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0)
|
MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0)
|
||||||
translatesAutoresizingMaskIntoConstraints = false
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
@ -82,7 +95,10 @@ open class Stack<T>: Container where T: StackModelProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
public override func reset() {
|
public override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
@ -91,7 +107,7 @@ open class Stack<T>: Container where T: StackModelProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
let previousModel = self.model
|
let previousModel = self.model
|
||||||
super.setWithModel(model, delegateObject, additionalData)
|
super.setWithModel(model, delegateObject, additionalData)
|
||||||
removeAllItemViews()
|
removeAllItemViews()
|
||||||
@ -132,6 +148,7 @@ open class Stack<T>: Container where T: StackModelProtocol {
|
|||||||
guard let model = molecule as? T else { return 0 }
|
guard let model = molecule as? T else { return 0 }
|
||||||
let horizontal = model.axis == .horizontal
|
let horizontal = model.axis == .horizontal
|
||||||
var estimatedHeight: CGFloat = 0
|
var estimatedHeight: CGFloat = 0
|
||||||
|
|
||||||
for case let item in model.molecules {
|
for case let item in model.molecules {
|
||||||
if item.gone { continue }
|
if item.gone { continue }
|
||||||
let height = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: item, delegateObject: delegateObject) ?? 0
|
let height = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: item, delegateObject: delegateObject) ?? 0
|
||||||
@ -158,26 +175,31 @@ open class Stack<T>: Container where T: StackModelProtocol {
|
|||||||
return modules.count > 0 ? modules : nil
|
return modules.count > 0 ? modules : nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
// MARK: - Subclassables
|
// MARK: - Subclassables
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
/// Can be subclassed to create views when we get stack item models and have no views yet
|
/// Can be subclassed to create views when we get stack item models and have no views yet
|
||||||
func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { }
|
||||||
}
|
|
||||||
|
|
||||||
/// Can be subclassed to set stack items with model when we already have views
|
/// Can be subclassed to set stack items with model when we already have views
|
||||||
func setStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
func setStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
guard let models = stackModel?.molecules else { return }
|
guard let models = stackModel?.molecules else { return }
|
||||||
for (index, element) in models.enumerated() {
|
for (index, element) in models.enumerated() {
|
||||||
(stackItems[index] as? ModelMoleculeViewProtocol)?.setWithModel(element, delegateObject, additionalData)
|
(stackItems[index] as? ModelMoleculeViewProtocol)?.setWithModel(element, delegateObject, additionalData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
// MARK: - Adding to stack
|
// MARK: - Adding to stack
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
/// Gets the percent modifier. This value is used to help properly calculate percent for stack items when spacing is involved.
|
/// Gets the percent modifier. This value is used to help properly calculate percent for stack items when spacing is involved.
|
||||||
private func getTotalSpace() -> CGFloat {
|
private func getTotalSpace() -> CGFloat {
|
||||||
guard let stackModel = stackModel else { return 0.0 }
|
guard let stackModel = stackModel else { return 0.0 }
|
||||||
var totalSpace: CGFloat = 0.0
|
var totalSpace: CGFloat = 0.0
|
||||||
var firstMoleculeFound = false
|
var firstMoleculeFound = false
|
||||||
|
|
||||||
for stackItemModel in stackModel.molecules {
|
for stackItemModel in stackModel.molecules {
|
||||||
guard !stackItemModel.gone else { continue }
|
guard !stackItemModel.gone else { continue }
|
||||||
let spacing = stackItemModel.spacing ?? stackModel.spacing
|
let spacing = stackItemModel.spacing ?? stackModel.spacing
|
||||||
@ -222,7 +244,7 @@ open class Stack<T>: Container where T: StackModelProtocol {
|
|||||||
pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0)
|
pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0)
|
||||||
pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0)
|
pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0)
|
||||||
if let percent = model.percent {
|
if let percent = model.percent {
|
||||||
let multiplier = CGFloat(percent)/100.0
|
let multiplier = CGFloat(percent) / 100.0
|
||||||
let constant = multiplier * totalSpacing
|
let constant = multiplier * totalSpacing
|
||||||
view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: multiplier, constant: -constant).isActive = true
|
view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: multiplier, constant: -constant).isActive = true
|
||||||
}
|
}
|
||||||
@ -241,7 +263,7 @@ open class Stack<T>: Container where T: StackModelProtocol {
|
|||||||
pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0)
|
pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0)
|
||||||
pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
|
pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
|
||||||
if let percent = model.percent {
|
if let percent = model.percent {
|
||||||
let multiplier = CGFloat(percent)/100.0
|
let multiplier = CGFloat(percent) / 100.0
|
||||||
let constant = multiplier * totalSpacing
|
let constant = multiplier * totalSpacing
|
||||||
view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: multiplier, constant: -constant).isActive = true
|
view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: multiplier, constant: -constant).isActive = true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,8 +16,9 @@ import Foundation
|
|||||||
public var spacing: CGFloat = 16.0
|
public var spacing: CGFloat = 16.0
|
||||||
public var useStackSpacingBeforeFirstItem = false
|
public var useStackSpacingBeforeFirstItem = false
|
||||||
|
|
||||||
public init(molecules: [StackItemModel]) {
|
public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis = .vertical) {
|
||||||
self.molecules = molecules
|
self.molecules = molecules
|
||||||
|
self.axis = axis
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user