merge from feature/coding

This commit is contained in:
Xinlei(Ryan) Pan 2020-01-24 15:13:04 -05:00
commit 085aa62c8b
15 changed files with 329 additions and 673 deletions

View File

@ -92,8 +92,10 @@
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.swift */; }; 0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.swift */; };
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; }; 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; };
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; }; 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; };
0ACDF26723D9F177002044B2 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ACDF26623D9F177002044B2 /* EntryFieldContainer.swift */; };
0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; }; 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; };
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; };
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; };
9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; };
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; };
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; };
9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; }; 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; };
@ -398,9 +400,11 @@
0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = "<group>"; }; 0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = "<group>"; };
0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = "<group>"; }; 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = "<group>"; };
0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = "<group>"; }; 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = "<group>"; };
0ACDF26623D9F177002044B2 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = "<group>"; };
0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; }; 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = "<group>"; };
31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = "<group>"; };
9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; }; 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; };
9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = "<group>"; };
943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = "<group>"; }; 943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = "<group>"; };
943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = "<group>"; }; 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = "<group>"; };
9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBarModel.swift; sourceTree = "<group>"; }; 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBarModel.swift; sourceTree = "<group>"; };
@ -707,7 +711,7 @@
0ABD1369237B18EE0081388D /* Views */ = { 0ABD1369237B18EE0081388D /* Views */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0ACDF26623D9F177002044B2 /* EntryFieldContainer.swift */, 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */,
D29E28DE23D740FC00ACEA85 /* Container */, D29E28DE23D740FC00ACEA85 /* Container */,
014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */, 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */,
D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */,
@ -1169,7 +1173,9 @@
D213347623843825008E41B3 /* Line.swift */, D213347623843825008E41B3 /* Line.swift */,
DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */, DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */,
94C2D9822386F3E30006CF46 /* Label */, 94C2D9822386F3E30006CF46 /* Label */,
31BE15CA23D8924C00452370 /* CheckboxModel.swift */,
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */,
31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */,
0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */, 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */,
01004F2F22721C3800991ECC /* RadioButton.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */,
D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */, D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */,
@ -1507,9 +1513,9 @@
files = ( files = (
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */, 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */,
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */, 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */,
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */,
94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */, 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */,
D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */, D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */,
0ACDF26723D9F177002044B2 /* EntryFieldContainer.swift in Sources */,
D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */, D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */,
DBC4391822442197001AB423 /* CaretView.swift in Sources */, DBC4391822442197001AB423 /* CaretView.swift in Sources */,
C07065C42395677300FBF997 /* Link.swift in Sources */, C07065C42395677300FBF997 /* Link.swift in Sources */,
@ -1597,6 +1603,7 @@
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */,
0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */, 0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */,
01509D952327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift in Sources */, 01509D952327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift in Sources */,
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */,
D260105523CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift in Sources */, D260105523CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift in Sources */,
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */, 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */,
@ -1683,6 +1690,7 @@
D28A839323CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift in Sources */, D28A839323CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift in Sources */,
D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */, D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */,
D260105F23D0BFFC00764D80 /* StackItem.swift in Sources */, D260105F23D0BFFC00764D80 /* StackItem.swift in Sources */,
9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */,
01EB369323609801006832FA /* HeaderModel.swift in Sources */, 01EB369323609801006832FA /* HeaderModel.swift in Sources */,
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */,
0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */, 0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */,

View File

@ -76,6 +76,27 @@ import MVMCore
} }
} }
open override var isEnabled: Bool {
didSet {
isUserInteractionEnabled = isEnabled
if isEnabled {
layer.borderColor = borderColor.cgColor
backgroundColor = isSelected ? checkedBackgroundColor : unCheckedBackgroundColor
setShapeLayerStrokeColor(checkColor)
} else {
layer.borderColor = disabledBorderColor.cgColor
backgroundColor = disabledBackgroundColor
setShapeLayerStrokeColor(disabledCheckColor)
}
}
}
public var disabledBackgroundColor: UIColor = .clear
public var disabledBorderColor: UIColor = .mvmCoolGray3
public var disabledCheckColor: UIColor = .mvmCoolGray3
/// Color of the check mark. /// Color of the check mark.
public var checkColor: UIColor = .black { public var checkColor: UIColor = .black {
didSet { didSet {
@ -107,7 +128,6 @@ import MVMCore
if !updateSelectionOnly { if !updateSelectionOnly {
layoutIfNeeded() layoutIfNeeded()
shapeLayer?.removeAllAnimations() shapeLayer?.removeAllAnimations()
updateCheckboxUI(isSelected: isSelected, isAnimated: isAnimated) updateCheckboxUI(isSelected: isSelected, isAnimated: isAnimated)
FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol)
updateAccessibilityLabel() updateAccessibilityLabel()
@ -154,16 +174,12 @@ import MVMCore
public convenience init(isChecked: Bool) { public convenience init(isChecked: Bool) {
self.init(frame: .zero) self.init(frame: .zero)
updateSelectionOnly = true checkAndBypassAnimations(selected: isChecked)
isSelected = isChecked
updateSelectionOnly = false
} }
public convenience init(checkedBackgroundColor: UIColor, unCheckedBackgroundColor: UIColor, isChecked: Bool = false) { public convenience init(checkedBackgroundColor: UIColor, unCheckedBackgroundColor: UIColor, isChecked: Bool = false) {
self.init(frame: .zero) self.init(frame: .zero)
updateSelectionOnly = true checkAndBypassAnimations(selected: isChecked)
isSelected = isChecked
updateSelectionOnly = false
self.checkedBackgroundColor = checkedBackgroundColor self.checkedBackgroundColor = checkedBackgroundColor
self.unCheckedBackgroundColor = unCheckedBackgroundColor self.unCheckedBackgroundColor = unCheckedBackgroundColor
} }
@ -177,8 +193,6 @@ import MVMCore
drawShapeLayer() drawShapeLayer()
layer.cornerRadius = isRound ? cornerRadiusValue : 0 layer.cornerRadius = isRound ? cornerRadiusValue : 0
layer.borderWidth = borderWidth
layer.borderColor = borderColor.cgColor
} }
open override func setupView() { open override func setupView() {
@ -228,7 +242,7 @@ import MVMCore
self.shapeLayer = shapeLayer self.shapeLayer = shapeLayer
shapeLayer.frame = bounds shapeLayer.frame = bounds
layer.addSublayer(shapeLayer) layer.addSublayer(shapeLayer)
shapeLayer.strokeColor = checkColor.cgColor shapeLayer.strokeColor = isEnabled ? checkColor.cgColor : disabledCheckColor.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.path = checkMarkPath() shapeLayer.path = checkMarkPath()
shapeLayer.lineJoin = .miter shapeLayer.lineJoin = .miter
@ -268,9 +282,7 @@ import MVMCore
DispatchQueue.main.async { DispatchQueue.main.async {
self.updateSelectionOnly = true self.checkAndBypassAnimations(selected: selected)
self.isSelected = selected
self.updateSelectionOnly = false
self.drawShapeLayer() self.drawShapeLayer()
self.shapeLayer?.removeAllAnimations() self.shapeLayer?.removeAllAnimations()
self.updateCheckboxUI(isSelected: selected, isAnimated: animated) self.updateCheckboxUI(isSelected: selected, isAnimated: animated)
@ -313,23 +325,6 @@ import MVMCore
} }
} }
func isEnabled(_ enabled: Bool) {
isUserInteractionEnabled = enabled
if enabled {
layer.borderColor = borderColor.cgColor
backgroundColor = isSelected ? checkedBackgroundColor : unCheckedBackgroundColor
alpha = 1.0
setShapeLayerStrokeColor(checkColor)
} else {
layer.borderColor = UIColor.mfSilver().cgColor
backgroundColor = .clear
alpha = DisableOppacity
setShapeLayerStrokeColor(UIColor.mfSilver())
}
}
private func setShapeLayerStrokeColor(_ color: UIColor) { private func setShapeLayerStrokeColor(_ color: UIColor) {
if let shapeLayer = shapeLayer { if let shapeLayer = shapeLayer {
@ -345,13 +340,19 @@ import MVMCore
widthConstraint?.isActive = isActive widthConstraint?.isActive = isActive
} }
private func checkAndBypassAnimations(selected: Bool) {
updateSelectionOnly = true
isSelected = selected
updateSelectionOnly = false
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - UITouch // MARK: - UITouch
//-------------------------------------------------- //--------------------------------------------------
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
sendActions(for: .touchUpInside) sendActions(for: .touchUpInside)
} }
override open func accessibilityActivate() -> Bool { override open func accessibilityActivate() -> Bool {
@ -370,7 +371,7 @@ import MVMCore
open override func reset() { open override func reset() {
super.reset() super.reset()
isEnabled(true) isEnabled = true
shapeLayer?.removeAllAnimations() shapeLayer?.removeAllAnimations()
shapeLayer?.removeFromSuperlayer() shapeLayer?.removeFromSuperlayer()
shapeLayer = nil shapeLayer = nil
@ -379,9 +380,7 @@ import MVMCore
borderWidth = 1.0 borderWidth = 1.0
checkColor = .black checkColor = .black
checkWidth = 2.0 checkWidth = 2.0
updateSelectionOnly = true checkAndBypassAnimations(selected: false)
isSelected = false
updateSelectionOnly = false
} }
open func setAsMolecule() { open func setAsMolecule() {
@ -424,16 +423,14 @@ import MVMCore
layer.borderWidth = borderWidth layer.borderWidth = borderWidth
} }
if let isChecked = dictionary["isChecked"] as? Bool, isChecked {
updateSelectionOnly = true
isSelected = isChecked
updateSelectionOnly = false
}
if let checkColorHex = dictionary["checkColor"] as? String { if let checkColorHex = dictionary["checkColor"] as? String {
checkColor = UIColor.mfGet(forHex: checkColorHex) checkColor = UIColor.mfGet(forHex: checkColorHex)
} }
if let isChecked = dictionary["isChecked"] as? Bool, isChecked {
checkAndBypassAnimations(selected: isChecked)
}
if let unCheckedBackgroundColorHex = dictionary["unCheckedBackgroundColor"] as? String { if let unCheckedBackgroundColorHex = dictionary["unCheckedBackgroundColor"] as? String {
unCheckedBackgroundColor = UIColor.mfGet(forHex: unCheckedBackgroundColorHex) unCheckedBackgroundColor = UIColor.mfGet(forHex: unCheckedBackgroundColorHex)
} }
@ -451,13 +448,57 @@ import MVMCore
} }
if let enabled = dictionary["isEnabled"] as? Bool { if let enabled = dictionary["isEnabled"] as? Bool {
isEnabled(enabled) isEnabled = enabled
} }
if let actionMap = dictionary.optionalDictionaryForKey("action") { if let actionMap = dictionary.optionalDictionaryForKey("action") {
actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) }
} }
} }
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? CheckboxModel else { return }
self.delegateObject = delegateObject
FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol)
groupName = model.groupName
fieldValue = model.value
isRequired = model.required
if let fieldKey = model.fieldKey {
self.fieldKey = fieldKey
}
borderColor = model.borderColor.uiColor
borderWidth = model.borderWidth
checkColor = model.checkColor.uiColor
unCheckedBackgroundColor = model.unCheckedBackgroundColor.uiColor
checkedBackgroundColor = model.checkedBackgroundColor.uiColor
disabledCheckColor = model.disabledCheckColor.uiColor
disabledBorderColor = model.disabledBorderColor.uiColor
disabledBackgroundColor = model.disabledBackgroundColor.uiColor
isAnimated = model.isAnimated
isRound = model.isRound
if model.isChecked {
checkAndBypassAnimations(selected: model.isChecked)
}
isEnabled = model.isEnabled
if let action = model.action {
actionBlock = {
if let actionMap = action.toJSON() {
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
}
}
}
}
} }
// MARK:- FormValidationProtocol // MARK:- FormValidationProtocol

View File

@ -0,0 +1,24 @@
//
// CheckboxWithLabelViewModel.swift
// MVMCoreUI
//
// Created by Chintakrinda, Arun Kumar (Arun) on 21/01/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public enum CheckboxPosition: String, Codable {
case center
case top
case bottom
}
@objcMembers public class CheckboxLabelModel: MoleculeModelProtocol {
public static var identifier: String = "checkboxLabel"
public var backgroundColor: Color?
public var checkboxAlignment: CheckboxPosition?
public var checkbox: CheckboxModel
public var label: LabelModel
}

View File

@ -0,0 +1,106 @@
//
// CheckboxModel.swift
// MVMCoreUI
//
// Created by Chintakrinda, Arun Kumar (Arun) on 21/01/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class CheckboxModel: MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "checkbox"
public var backgroundColor: Color?
public var groupName: String?
public var value: String?
public var fieldKey: String?
public var required: Bool = false
public var borderColor: Color = Color(uiColor: .black)
public var borderWidth: CGFloat = 1
public var isChecked: Bool = false
public var checkColor: Color = Color(uiColor: .black)
public var unCheckedBackgroundColor: Color = Color(uiColor: .clear)
public var checkedBackgroundColor: Color = Color(uiColor: .clear)
public var isAnimated: Bool = true
public var isRound: Bool = false
public var isEnabled: Bool = true
public var action: ActionModelProtocol?
public var disabledBackgroundColor: Color = Color(uiColor: .clear)
public var disabledBorderColor: Color = Color(uiColor: .mvmCoolGray3)
public var disabledCheckColor: Color = Color(uiColor: .mvmCoolGray3)
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case groupName
case value
case fieldKey
case required
case borderColor
case borderWidth
case isChecked
case checkColor
case unCheckedBackgroundColor
case checkedBackgroundColor
case disabledBackgroundColor
case disabledCheckColor
case disabledBorderColor
case isAnimated
case isRound
case isEnabled
case action
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName)
value = try typeContainer.decodeIfPresent(String.self, forKey: .value)
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) ?? false
borderWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .borderWidth) ?? 1
borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) ?? Color(uiColor: .black)
checkColor = try typeContainer.decodeIfPresent(Color.self, forKey: .checkColor) ?? Color(uiColor: .black)
unCheckedBackgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .unCheckedBackgroundColor) ?? Color(uiColor: .clear)
checkedBackgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .checkedBackgroundColor) ?? Color(uiColor: .clear)
disabledBackgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBackgroundColor) ?? Color(uiColor: .clear)
disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor) ?? Color(uiColor: .mvmCoolGray3)
disabledCheckColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledCheckColor) ?? Color(uiColor: .mvmCoolGray3)
isChecked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isChecked) ?? false
isAnimated = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAnimated) ?? true
isRound = try typeContainer.decodeIfPresent(Bool.self, forKey: .isRound) ?? false
isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true
action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encodeIfPresent(value, forKey: .value)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(required, forKey: .required)
try container.encodeIfPresent(borderColor, forKey: .borderColor)
try container.encode(borderWidth, forKey: .borderWidth)
try container.encode(isChecked, forKey: .isChecked)
try container.encodeIfPresent(checkColor, forKey: .checkColor)
try container.encodeIfPresent(unCheckedBackgroundColor, forKey: .unCheckedBackgroundColor)
try container.encodeIfPresent(checkedBackgroundColor, forKey: .checkedBackgroundColor)
try container.encodeIfPresent(disabledBorderColor, forKey: .disabledBorderColor)
try container.encodeIfPresent(disabledBackgroundColor, forKey: .disabledBackgroundColor)
try container.encodeIfPresent(disabledCheckColor, forKey: .disabledCheckColor)
try container.encodeIfPresent(isAnimated, forKey: .isAnimated)
try container.encodeIfPresent(isRound, forKey: .isRound)
try container.encodeIfPresent(isEnabled, forKey: .isEnabled)
try container.encodeModelIfPresent(action, forKey: .action)
}
}

View File

@ -21,12 +21,6 @@
public var checkboxPosition: CheckboxPosition = .center public var checkboxPosition: CheckboxPosition = .center
public enum CheckboxPosition: String {
case center
case top
case bottom
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Constraints // MARK: - Constraints
//-------------------------------------------------- //--------------------------------------------------
@ -120,6 +114,17 @@
checkboxCenterYConstraint?.isActive = false checkboxCenterYConstraint?.isActive = false
} }
} }
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let checkBoxWithLabelModel = model as? CheckboxLabelModel else { return }
if let checkboxAlignment = checkBoxWithLabelModel.checkboxAlignment {
alignCheckbox(checkboxAlignment)
}
checkbox.setWithModel(checkBoxWithLabelModel.checkbox, delegateObject, additionalData)
label.setWithModel(checkBoxWithLabelModel.label, delegateObject, additionalData)
}
} }
// MARK: - Molecular // MARK: - Molecular

View File

@ -19,6 +19,9 @@ open class DashLine: View {
get { return model as? DashLineModel } get { return model as? DashLineModel }
} }
//TODO: Need this for BAU. Can remove once we fix BAU
public var dashColor: UIColor?
@objc private var dashLayer: CAShapeLayer? @objc private var dashLayer: CAShapeLayer?
//------------------------------------------------------ //------------------------------------------------------
@ -68,7 +71,7 @@ open class DashLine: View {
dashLayer.lineCap = .round dashLayer.lineCap = .round
dashLayer.lineDashPattern = [NSNumber(value: 2), NSNumber(value: 2)] dashLayer.lineDashPattern = [NSNumber(value: 2), NSNumber(value: 2)]
dashLayer.path = path.cgPath dashLayer.path = path.cgPath
dashLayer.strokeColor = dashModel?.dashColor.cgColor dashLayer.strokeColor = dashModel?.dashColor.cgColor ?? dashColor?.cgColor
dashLayer.fillColor = UIColor.clear.cgColor dashLayer.fillColor = UIColor.clear.cgColor
dashLayer.backgroundColor = backgroundColor?.cgColor ?? UIColor.white.cgColor dashLayer.backgroundColor = backgroundColor?.cgColor ?? UIColor.white.cgColor
self.dashLayer = dashLayer self.dashLayer = dashLayer

View File

@ -315,7 +315,7 @@ public typealias ActionBlock = () -> ()
} }
case let actionAtt as LabelAttributeActionModel: case let actionAtt as LabelAttributeActionModel:
addTappableLinkAttribute(range: NSRange(location: range.location, length: range.length)) { addTappableLinkAttribute(range: NSRange(location: range.location, length: range.length)) {
if let data = try? actionAtt.encode(using: JSONEncoder()), let actionMap = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.init()) as? [AnyHashable: Any] { if let data = try? actionAtt.action.encode(using: JSONEncoder()), let actionMap = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.init()) as? [AnyHashable: Any] {
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
} }
} }

View File

@ -43,7 +43,9 @@ import UIKit
public static var identifier: String = "line" public static var identifier: String = "line"
public var type: Style = .standard public var type: Style = .standard
public var frequency: Frequency? = .allExceptTop public var frequency: Frequency? = .allExceptTop
public var color: Color?
//TODO: use color insted of backgroundColor. Needs server changes
// public var color: Color?
public var backgroundColor: Color? public var backgroundColor: Color?
public init(type: Style) { public init(type: Style) {
@ -66,7 +68,7 @@ import UIKit
if let frequency = try typeContainer.decodeIfPresent(Frequency.self, forKey: .frequency) { if let frequency = try typeContainer.decodeIfPresent(Frequency.self, forKey: .frequency) {
self.frequency = frequency self.frequency = frequency
} }
color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -74,6 +76,6 @@ import UIKit
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(type, forKey: .type) try container.encode(type, forKey: .type)
try container.encodeIfPresent(frequency, forKey: .frequency) try container.encodeIfPresent(frequency, forKey: .frequency)
try container.encodeIfPresent(color, forKey: .color) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
} }
} }

View File

@ -1,293 +0,0 @@
//
// EntryFieldContainer.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 11/12/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers open class EntryFieldContainer: View {
//--------------------------------------------------
// MARK: - Drawing Properties
//--------------------------------------------------
/// The bottom border line. Height is dynamic based on scenario.
public var bottomBar: CAShapeLayer? = {
let layer = CAShapeLayer()
layer.backgroundColor = UIColor.black.cgColor
layer.drawsAsynchronously = true
layer.anchorPoint = CGPoint(x: 0.5, y: 1.0);
return layer
}()
/// Total control over the drawn top, bottom, left and right borders.
public var disableAllBorders = false {
didSet {
bottomBar?.isHidden = disableAllBorders
}
}
private(set) var fieldState: FieldState = .original {
didSet (oldState) {
// Will not update if new state is the same as old.
if fieldState != oldState {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.fieldState.setStateUI(for: self)
}
}
}
}
/// Determines if the top, left, and right borders should be drawn.
private var hideBorders = false
public var borderStrokeColor: UIColor = .mfSilver()
private var borderPath: UIBezierPath = UIBezierPath()
//--------------------------------------------------
// MARK: - Property Observers
//--------------------------------------------------
private var _isEnabled: Bool = true
private var _showError: Bool = false
private var _isLocked: Bool = false
private var _isSelected: Bool = false
public var isEnabled: Bool {
get { return _isEnabled }
set (enabled) {
_isEnabled = enabled
_isLocked = false
_isSelected = false
_showError = false
fieldState = enabled ? .original : .disabled
}
}
public var showError: Bool {
get { return _showError }
set (error) {
_showError = error
_isEnabled = true
_isLocked = false
_isSelected = false
fieldState = error ? .error : .original
}
}
public var isLocked: Bool {
get { return _isLocked }
set (locked) {
_isLocked = locked
_isEnabled = true
_isSelected = false
_showError = false
fieldState = locked ? .locked : .original
}
}
public var isSelected: Bool {
get { return _isSelected }
set (selected) {
_isSelected = selected
_isLocked = false
_isEnabled = true
if _showError {
fieldState = selected ? .selectedError : .error
} else {
fieldState = selected ? .selected : .original
}
}
}
//--------------------------------------------------
// MARK: - Delegate
//--------------------------------------------------
/// Holds reference to delegateObject to inform molecular tableView of an update.
var delegateObject: MVMCoreUIDelegateObject?
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func layoutSubviews() {
super.layoutSubviews()
refreshUI(bottomBarSize: showError ? 4 : 1)
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
refreshUI()
}
/// This handles the top, left, and right border lines.
open override func draw(_ rect: CGRect) {
super.draw(rect)
borderPath.removeAllPoints()
if !disableAllBorders && !hideBorders {
// Brings the other half of the line inside the view to prevent cropping.
let origin = bounds.origin
let size = frame.size
let insetLean: CGFloat = 0.5
borderPath.lineWidth = 1
borderPath.move(to: CGPoint(x: origin.x + insetLean, y: origin.y + size.height))
borderPath.addLine(to: CGPoint(x: origin.x + insetLean, y: origin.y + insetLean))
borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + insetLean))
borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + size.height))
borderStrokeColor.setStroke()
borderPath.stroke()
}
}
override open func setupView() {
super.setupView()
isAccessibilityElement = false
isOpaque = false
if let bottomBar = bottomBar {
layer.addSublayer(bottomBar)
}
}
//--------------------------------------------------
// MARK: - Draw States
//--------------------------------------------------
public enum FieldState {
case original
case error
case selectedError
case selected
case locked
case disabled
public func setStateUI(for formField: EntryFieldContainer) {
switch self {
case .original:
formField.originalUI()
case .error:
formField.errorUI()
case .selectedError:
formField.selectedErrorUI()
case .selected:
formField.selectedUI()
case .locked:
formField.lockedUI()
case .disabled:
formField.disabledUI()
}
}
}
open func originalUI() {
isUserInteractionEnabled = true
hideBorders = false
borderStrokeColor = .mfSilver()
bottomBar?.backgroundColor = UIColor.black.cgColor
refreshUI(bottomBarSize: 1)
}
open func errorUI() {
isUserInteractionEnabled = true
hideBorders = false
borderStrokeColor = .mfPumpkin()
bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor
refreshUI(bottomBarSize: 4)
}
open func selectedErrorUI() {
isUserInteractionEnabled = true
hideBorders = false
borderStrokeColor = .black
bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor
refreshUI(bottomBarSize: 4)
}
open func selectedUI() {
isUserInteractionEnabled = true
hideBorders = false
borderStrokeColor = .black
bottomBar?.backgroundColor = UIColor.black.cgColor
refreshUI(bottomBarSize: 1)
}
open func lockedUI() {
isUserInteractionEnabled = false
hideBorders = true
borderStrokeColor = .clear
bottomBar?.backgroundColor = UIColor.clear.cgColor
refreshUI(bottomBarSize: 1)
}
open func disabledUI() {
isUserInteractionEnabled = false
hideBorders = false
borderStrokeColor = .mfSilver()
bottomBar?.backgroundColor = UIColor.mfSilver().cgColor
refreshUI(bottomBarSize: 1)
}
open func refreshUI(bottomBarSize: CGFloat? = nil) {
if !disableAllBorders {
let size: CGFloat = bottomBarSize ?? (showError ? 4 : 1)
bottomBar?.frame = CGRect(x: 0, y: bounds.height - size, width: bounds.width, height: size)
delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
setNeedsDisplay()
layoutIfNeeded()
}
}
//--------------------------------------------------
// MARK: - MVMCoreUIMoleculeViewProtocol
//--------------------------------------------------
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData)
self.delegateObject = delegateObject
}
}
extension EntryFieldContainer {
override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
self.delegateObject = delegateObject
guard let dictionary = json, !dictionary.isEmpty else { return }
}
}

View File

@ -1,293 +0,0 @@
//
// EntryFieldContainer.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 11/12/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers open class EntryFieldContainer: View {
//--------------------------------------------------
// MARK: - Drawing Properties
//--------------------------------------------------
/// The bottom border line. Height is dynamic based on scenario.
public var bottomBar: CAShapeLayer? = {
let layer = CAShapeLayer()
layer.backgroundColor = UIColor.black.cgColor
layer.drawsAsynchronously = true
layer.anchorPoint = CGPoint(x: 0.5, y: 1.0);
return layer
}()
/// Total control over the drawn top, bottom, left and right borders.
public var disableAllBorders = false {
didSet {
bottomBar?.isHidden = disableAllBorders
}
}
private(set) var fieldState: FieldState = .original {
didSet (oldState) {
// Will not update if new state is the same as old.
if fieldState != oldState {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.fieldState.setStateUI(for: self)
}
}
}
}
/// Determines if the top, left, and right borders should be drawn.
private var hideBorders = false
public var borderStrokeColor: UIColor = .mfSilver()
private var borderPath: UIBezierPath = UIBezierPath()
//--------------------------------------------------
// MARK: - Property Observers
//--------------------------------------------------
private var _isEnabled: Bool = true
private var _showError: Bool = false
private var _isLocked: Bool = false
private var _isSelected: Bool = false
public var isEnabled: Bool {
get { return _isEnabled }
set (enabled) {
_isEnabled = enabled
_isLocked = false
_isSelected = false
_showError = false
fieldState = enabled ? .original : .disabled
}
}
public var showError: Bool {
get { return _showError }
set (error) {
_showError = error
_isEnabled = true
_isLocked = false
_isSelected = false
fieldState = error ? .error : .original
}
}
public var isLocked: Bool {
get { return _isLocked }
set (locked) {
_isLocked = locked
_isEnabled = true
_isSelected = false
_showError = false
fieldState = locked ? .locked : .original
}
}
public var isSelected: Bool {
get { return _isSelected }
set (selected) {
_isSelected = selected
_isLocked = false
_isEnabled = true
if _showError {
fieldState = selected ? .selectedError : .error
} else {
fieldState = selected ? .selected : .original
}
}
}
//--------------------------------------------------
// MARK: - Delegate
//--------------------------------------------------
/// Holds reference to delegateObject to inform molecular tableView of an update.
var delegateObject: MVMCoreUIDelegateObject?
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func layoutSubviews() {
super.layoutSubviews()
refreshUI(bottomBarSize: showError ? 4 : 1)
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
refreshUI()
}
/// This handles the top, left, and right border lines.
open override func draw(_ rect: CGRect) {
super.draw(rect)
borderPath.removeAllPoints()
if !disableAllBorders && !hideBorders {
// Brings the other half of the line inside the view to prevent cropping.
let origin = bounds.origin
let size = frame.size
let insetLean: CGFloat = 0.5
borderPath.lineWidth = 1
borderPath.move(to: CGPoint(x: origin.x + insetLean, y: origin.y + size.height))
borderPath.addLine(to: CGPoint(x: origin.x + insetLean, y: origin.y + insetLean))
borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + insetLean))
borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + size.height))
borderStrokeColor.setStroke()
borderPath.stroke()
}
}
override open func setupView() {
super.setupView()
isAccessibilityElement = false
isOpaque = false
if let bottomBar = bottomBar {
layer.addSublayer(bottomBar)
}
}
//--------------------------------------------------
// MARK: - Draw States
//--------------------------------------------------
public enum FieldState {
case original
case error
case selectedError
case selected
case locked
case disabled
public func setStateUI(for formField: EntryFieldContainer) {
switch self {
case .original:
formField.originalUI()
case .error:
formField.errorUI()
case .selectedError:
formField.selectedErrorUI()
case .selected:
formField.selectedUI()
case .locked:
formField.lockedUI()
case .disabled:
formField.disabledUI()
}
}
}
open func originalUI() {
isUserInteractionEnabled = true
hideBorders = false
borderStrokeColor = .mfSilver()
bottomBar?.backgroundColor = UIColor.black.cgColor
refreshUI(bottomBarSize: 1)
}
open func errorUI() {
isUserInteractionEnabled = true
hideBorders = false
borderStrokeColor = .mfPumpkin()
bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor
refreshUI(bottomBarSize: 4)
}
open func selectedErrorUI() {
isUserInteractionEnabled = true
hideBorders = false
borderStrokeColor = .black
bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor
refreshUI(bottomBarSize: 4)
}
open func selectedUI() {
isUserInteractionEnabled = true
hideBorders = false
borderStrokeColor = .black
bottomBar?.backgroundColor = UIColor.black.cgColor
refreshUI(bottomBarSize: 1)
}
open func lockedUI() {
isUserInteractionEnabled = false
hideBorders = true
borderStrokeColor = .clear
bottomBar?.backgroundColor = UIColor.clear.cgColor
refreshUI(bottomBarSize: 1)
}
open func disabledUI() {
isUserInteractionEnabled = false
hideBorders = false
borderStrokeColor = .mfSilver()
bottomBar?.backgroundColor = UIColor.mfSilver().cgColor
refreshUI(bottomBarSize: 1)
}
open func refreshUI(bottomBarSize: CGFloat? = nil) {
if !disableAllBorders {
let size: CGFloat = bottomBarSize ?? (showError ? 4 : 1)
bottomBar?.frame = CGRect(x: 0, y: bounds.height - size, width: bounds.width, height: size)
delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
setNeedsDisplay()
layoutIfNeeded()
}
}
//--------------------------------------------------
// MARK: - MVMCoreUIMoleculeViewProtocol
//--------------------------------------------------
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData)
self.delegateObject = delegateObject
}
}
extension EntryFieldContainer {
override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
self.delegateObject = delegateObject
guard let dictionary = json, !dictionary.isEmpty else { return }
}
}

View File

@ -137,6 +137,7 @@ import UIKit
open func setupView() { open func setupView() {
selectionStyle = .none selectionStyle = .none
insetsLayoutMarginsFromSafeArea = false insetsLayoutMarginsFromSafeArea = false
preservesSuperviewLayoutMargins = false
contentView.insetsLayoutMarginsFromSafeArea = false contentView.insetsLayoutMarginsFromSafeArea = false
contentView.preservesSuperviewLayoutMargins = false contentView.preservesSuperviewLayoutMargins = false
} }

View File

@ -7,13 +7,15 @@
// //
import Foundation import Foundation
@objcMembers public class HeadLineBodyCaretLinkImage: View { @objcMembers public class HeadLineBodyCaretLinkImage: Container {
let headlineBody = HeadlineBody(frame: .zero) let headlineBody = HeadlineBody(frame: .zero)
let caretButton = CaretButton(frame: .zero) let caretButton = CaretButton(frame: .zero)
let backgroundImageView = MFLoadImageView() let backgroundImageView = MFLoadImageView(pinnedEdges: .all)
var spaceBetweenConstant: CGFloat = 104.0 var spaceBetweenConstant: CGFloat = 104.0
let maxWidth : CGFloat = 350.0 let maxWidth: CGFloat = 350.0
static let heightConstant: CGFloat = 320.0
var heightConstraint: NSLayoutConstraint?
// MARK: - MVMCoreViewProtocol // MARK: - MVMCoreViewProtocol
open override func updateView(_ size: CGFloat) { open override func updateView(_ size: CGFloat) {
super.updateView(size) super.updateView(size)
@ -29,25 +31,28 @@ import Foundation
guard subviews.count == 0 else { guard subviews.count == 0 else {
return return
} }
let view = MVMCoreUICommonViewsUtility.commonView() heightConstraint = heightAnchor.constraint(equalToConstant: Self.heightConstant)
addSubview(view) heightConstraint?.isActive = true
NSLayoutConstraint.constraintPinSubview(toSuperview: view)
view.addSubview(headlineBody) let container = MVMCoreUICommonViewsUtility.commonView()
view.addSubview(caretButton) addAndContain(container)
container.addSubview(headlineBody)
container.addSubview(caretButton)
//Headline view //Headline view
headlineBody.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true headlineBody.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
headlineBody.topAnchor.constraint(equalTo: view.topAnchor, constant: PaddingDefault).isActive = true headlineBody.topAnchor.constraint(equalTo: container.topAnchor, constant: 0).isActive = true
let headLineBodyWidth = headlineBody.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.85) let headLineBodyWidth = headlineBody.widthAnchor.constraint(equalTo: container.widthAnchor, multiplier: 0.85)
headLineBodyWidth.priority = .defaultHigh headLineBodyWidth.priority = .defaultHigh
headLineBodyWidth.isActive = true headLineBodyWidth.isActive = true
headlineBody.widthAnchor.constraint(lessThanOrEqualToConstant: maxWidth).isActive = true headlineBody.widthAnchor.constraint(lessThanOrEqualToConstant: maxWidth).isActive = true
//Caret view //Caret view
caretButton.translatesAutoresizingMaskIntoConstraints = false caretButton.translatesAutoresizingMaskIntoConstraints = false
caretButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true caretButton.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
view.bottomAnchor.constraint(equalTo: caretButton.bottomAnchor, constant: PaddingDefault).isActive = true container.bottomAnchor.constraint(equalTo: caretButton.bottomAnchor, constant: 0).isActive = true
caretButton.topAnchor.constraint(greaterThanOrEqualTo: headlineBody.bottomAnchor, constant: spaceBetweenConstant).isActive = true caretButton.topAnchor.constraint(greaterThanOrEqualTo: headlineBody.bottomAnchor, constant: spaceBetweenConstant).isActive = true
@ -56,9 +61,9 @@ import Foundation
backgroundImageView.imageView.contentMode = .scaleAspectFill backgroundImageView.imageView.contentMode = .scaleAspectFill
backgroundImageView.alignFillHorizontal() backgroundImageView.alignFillHorizontal()
backgroundImageView.alignFillVertical() backgroundImageView.alignFillVertical()
view.addSubview(backgroundImageView) addSubview(backgroundImageView)
NSLayoutConstraint.constraintPinSubview(toSuperview: backgroundImageView) NSLayoutConstraint.constraintPinSubview(toSuperview: backgroundImageView)
view.sendSubviewToBack(backgroundImageView) sendSubviewToBack(backgroundImageView)
} }
// MARK: - MVMCoreUIMoleculeViewProtocol // MARK: - MVMCoreUIMoleculeViewProtocol
@ -85,6 +90,7 @@ import Foundation
guard let model = model as? HeadlineBodyCaretLinkImageModel else { return } guard let model = model as? HeadlineBodyCaretLinkImageModel else { return }
headlineBody.setWithModel(model.headlineBody, delegateObject, additionalData) headlineBody.setWithModel(model.headlineBody, delegateObject, additionalData)
caretButton.setWithModel(model.caretLink, delegateObject, additionalData) caretButton.setWithModel(model.caretLink, delegateObject, additionalData)
caretButton.isHidden = model.caretLink == nil
backgroundImageView.setWithModel(model.image, delegateObject, additionalData) backgroundImageView.setWithModel(model.image, delegateObject, additionalData)
backgroundImageView.alignFillHorizontal() backgroundImageView.alignFillHorizontal()
backgroundImageView.alignFillVertical() backgroundImageView.alignFillVertical()

View File

@ -8,10 +8,64 @@
import UIKit import UIKit
public class HeadlineBodyCaretLinkImageModel: MoleculeModelProtocol { public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProtocol {
public static var identifier: String = "headlineBodyCaretLinkImage" public static var identifier: String = "headlineBodyCaretLinkImage"
public var backgroundColor: Color? public var backgroundColor: Color?
public var caretLink: CaretLinkModel? public var caretLink: CaretLinkModel?
public var headlineBody: HeadlineBodyModel public var headlineBody: HeadlineBodyModel
public var image: ImageViewModel public var image: ImageViewModel
init(headlineBody: HeadlineBodyModel, image: ImageViewModel) {
self.headlineBody = headlineBody
self.image = image
super.init()
setDefaults()
}
/// Defaults to set
func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
if useVerticalMargins == nil {
useVerticalMargins = true
}
if topMarginPadding == nil {
topMarginPadding = PaddingDefault
}
if bottomMarginPadding == nil {
bottomMarginPadding = PaddingDefault
}
if image.height == nil {
image.height = HeadLineBodyCaretLinkImage.heightConstant
}
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case headlineBody
case image
case caretLink
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody)
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 {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(HeadlineBodyCaretLinkImageModel.identifier, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encode(headlineBody, forKey: .headlineBody)
try container.encode(image, forKey: .image)
try container.encodeIfPresent(caretLink, forKey: .caretLink)
}
} }

View File

@ -49,6 +49,8 @@ import Foundation
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Line.self, viewModelClass: LineModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Line.self, viewModelClass: LineModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: GraphView.self, viewModelClass: CircleProgressModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: GraphView.self, viewModelClass: CircleProgressModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Toggle.self, viewModelClass: ToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Toggle.self, viewModelClass: ToggleModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CheckboxWithLabelView.self, viewModelClass: CheckboxLabelModel.self)
// Horizontal Combination Molecules // Horizontal Combination Molecules
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self)

View File

@ -60,28 +60,18 @@ extension NSLayoutConstraint.Axis: RawRepresentable {
} }
} }
@propertyWrapper extension NSLayoutConstraint.Axis: Codable {
public struct Axis {
public var wrappedValue: NSLayoutConstraint.Axis
public init(wrappedValue value: NSLayoutConstraint.Axis) {
self.wrappedValue = value
}
}
extension Axis: Codable {
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
let typeContainer = try decoder.singleValueContainer() let typeContainer = try decoder.singleValueContainer()
let string = try typeContainer.decode(String.self) let string = try typeContainer.decode(String.self)
guard let axis = NSLayoutConstraint.Axis(rawValue: string) else { guard let axis = NSLayoutConstraint.Axis(rawValue: string) else {
throw AxisError.notAnAxis throw AxisError.notAnAxis
} }
wrappedValue = axis self = axis
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
let string = wrappedValue.rawValueString
var container = encoder.singleValueContainer() var container = encoder.singleValueContainer()
try container.encode(string) try container.encode(rawValueString)
} }
} }