Code refactoring by using collection base classes.
This commit is contained in:
parent
3daf3bc438
commit
1635353989
@ -190,6 +190,7 @@
|
|||||||
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; };
|
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; };
|
||||||
AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; };
|
AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; };
|
||||||
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; };
|
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; };
|
||||||
|
AA85236C244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */; };
|
||||||
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; };
|
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; };
|
||||||
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; };
|
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; };
|
||||||
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; };
|
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; };
|
||||||
@ -619,6 +620,7 @@
|
|||||||
AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = "<group>"; };
|
AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = "<group>"; };
|
||||||
AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = "<group>"; };
|
AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = "<group>"; };
|
||||||
AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = "<group>"; };
|
AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = "<group>"; };
|
||||||
|
AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchItemCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = "<group>"; };
|
AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = "<group>"; };
|
||||||
AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = "<group>"; };
|
AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = "<group>"; };
|
||||||
AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = "<group>"; };
|
AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = "<group>"; };
|
||||||
@ -1435,6 +1437,10 @@
|
|||||||
01004F2F22721C3800991ECC /* RadioButton.swift */,
|
01004F2F22721C3800991ECC /* RadioButton.swift */,
|
||||||
31BE15CA23D8924C00452370 /* CheckboxModel.swift */,
|
31BE15CA23D8924C00452370 /* CheckboxModel.swift */,
|
||||||
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */,
|
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */,
|
||||||
|
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */,
|
||||||
|
AAB9C10724346F4B00151545 /* RadioSwatches.swift */,
|
||||||
|
AAB9C109243496DD00151545 /* RadioSwatchItem.swift */,
|
||||||
|
AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */,
|
||||||
);
|
);
|
||||||
path = Selectors;
|
path = Selectors;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1515,9 +1521,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D264FAA8243FE17A00D98315 /* Selectors */,
|
D264FAA8243FE17A00D98315 /* Selectors */,
|
||||||
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */,
|
|
||||||
AAB9C10724346F4B00151545 /* RadioSwatches.swift */,
|
|
||||||
AAB9C109243496DD00151545 /* RadioSwatchItem.swift */,
|
|
||||||
D29DF22B21E6A0FA003B2FB9 /* TextFields */,
|
D29DF22B21E6A0FA003B2FB9 /* TextFields */,
|
||||||
D29DF17D21E69E26003B2FB9 /* Views */,
|
D29DF17D21E69E26003B2FB9 /* Views */,
|
||||||
D29DF16821E69E1F003B2FB9 /* Buttons */,
|
D29DF16821E69E1F003B2FB9 /* Buttons */,
|
||||||
@ -2330,6 +2333,7 @@
|
|||||||
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
|
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
|
||||||
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */,
|
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */,
|
||||||
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
|
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
|
||||||
|
AA85236C244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift in Sources */,
|
||||||
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */,
|
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */,
|
||||||
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
|
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
|
||||||
0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */,
|
0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */,
|
||||||
|
|||||||
@ -1,127 +0,0 @@
|
|||||||
//
|
|
||||||
// RadioSwatchItem.swift
|
|
||||||
// MVMCoreUI
|
|
||||||
//
|
|
||||||
// Created by Lekshmi S on 01/04/20.
|
|
||||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol {
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - Properties
|
|
||||||
//--------------------------------------------------
|
|
||||||
public var bottomText = Label(frame: .zero)
|
|
||||||
let circleLayer = CAShapeLayer()
|
|
||||||
var cellView = MVMCoreUICommonViewsUtility.commonView()
|
|
||||||
var fillColor: Color = Color(uiColor: .mvmBlue)
|
|
||||||
|
|
||||||
//------------------------------------------------------
|
|
||||||
// MARK: - Property Observer
|
|
||||||
//------------------------------------------------------
|
|
||||||
open override var isSelected: Bool {
|
|
||||||
didSet {
|
|
||||||
drawCircle()
|
|
||||||
isSelected ? drawOuterCircle() : removeOuterCircle()
|
|
||||||
isSelected ? (bottomText.isHidden = false) : (bottomText.isHidden = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var isStrikeThrough: Bool = false {
|
|
||||||
didSet {
|
|
||||||
cellView.layer.sublayers?.filter({$0.name == "OutOfStock"}).forEach({$0.removeFromSuperlayer()})
|
|
||||||
if isStrikeThrough {
|
|
||||||
drawStrikeThrough()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------
|
|
||||||
// MARK: - Initialization
|
|
||||||
//------------------------------------------------------
|
|
||||||
public override init(frame: CGRect) {
|
|
||||||
super.init(frame: .zero)
|
|
||||||
setupView()
|
|
||||||
}
|
|
||||||
|
|
||||||
public required init?(coder aDecoder: NSCoder) {
|
|
||||||
super.init(coder: aDecoder)
|
|
||||||
setupView()
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------
|
|
||||||
// MARK: - Drawing
|
|
||||||
//------------------------------------------------------
|
|
||||||
public func drawCircle() {
|
|
||||||
cellView.layer.sublayers?.filter({$0.name == "InnerCircle"}).forEach({$0.removeFromSuperlayer()})
|
|
||||||
circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath
|
|
||||||
circleLayer.fillColor = fillColor.cgColor
|
|
||||||
circleLayer.strokeColor = isUserInteractionEnabled ? UIColor.mvmBlack.cgColor : UIColor.mvmCoolGray6.cgColor
|
|
||||||
circleLayer.name = "InnerCircle"
|
|
||||||
circleLayer.lineWidth = 1
|
|
||||||
cellView.layer.addSublayer(circleLayer)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func drawStrikeThrough() {
|
|
||||||
let startPoint = CGPoint(x: 12, y: 30)
|
|
||||||
let endPoint = CGPoint(x: 42, y: 0)
|
|
||||||
let bezierPath = UIBezierPath()
|
|
||||||
bezierPath.move(to: startPoint)
|
|
||||||
bezierPath.addLine(to: endPoint)
|
|
||||||
let strikeThroughLayer = CAShapeLayer()
|
|
||||||
strikeThroughLayer.path = bezierPath.cgPath
|
|
||||||
strikeThroughLayer.name = "OutOfStock"
|
|
||||||
strikeThroughLayer.strokeColor = UIColor.mvmCoolGray6.cgColor
|
|
||||||
strikeThroughLayer.lineWidth = 1
|
|
||||||
cellView.layer.addSublayer(strikeThroughLayer)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func drawOuterCircle() {
|
|
||||||
self.cellView.layer.sublayers?.filter({$0.name == "OuterCircle"}).forEach({$0.removeFromSuperlayer()})
|
|
||||||
circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 15, y: 4, width: 24, height: 24)).cgPath
|
|
||||||
let outerCircleLayer = CAShapeLayer()
|
|
||||||
outerCircleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath
|
|
||||||
outerCircleLayer.name = "OuterCircle"
|
|
||||||
outerCircleLayer.strokeColor = UIColor.mvmBlack.cgColor
|
|
||||||
outerCircleLayer.fillColor = UIColor.clear.cgColor
|
|
||||||
outerCircleLayer.lineWidth = 1
|
|
||||||
cellView.layer.addSublayer(outerCircleLayer)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func removeOuterCircle() {
|
|
||||||
circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath
|
|
||||||
self.cellView.layer.sublayers?.filter({$0.name == "OuterCircle"}).forEach({$0.removeFromSuperlayer()})
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - Lifecycle
|
|
||||||
//--------------------------------------------------
|
|
||||||
public func setupView() {
|
|
||||||
guard cellView.superview == nil else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
isAccessibilityElement = false
|
|
||||||
contentView.isAccessibilityElement = false
|
|
||||||
insetsLayoutMarginsFromSafeArea = false
|
|
||||||
contentView.insetsLayoutMarginsFromSafeArea = false
|
|
||||||
contentView.preservesSuperviewLayoutMargins = false
|
|
||||||
contentView.addSubview(cellView)
|
|
||||||
NSLayoutConstraint.constraintPinSubview(toSuperview: cellView)
|
|
||||||
cellView.addSubview(bottomText)
|
|
||||||
bottomText.textAlignment = .center
|
|
||||||
bottomText.font = MFFonts.mfFontTXRegular(11.0)
|
|
||||||
bottomText.topAnchor.constraint(equalTo: cellView.topAnchor, constant: 38).isActive = true
|
|
||||||
bottomText.leadingAnchor.constraint(equalTo: cellView.leadingAnchor).isActive = true
|
|
||||||
bottomText.trailingAnchor.constraint(equalTo: cellView.trailingAnchor).isActive = true
|
|
||||||
cellView.bottomAnchor.constraint(equalTo: bottomText.bottomAnchor).isActive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
|
||||||
guard let collectionModel = model as? RadioSwatchItemModel else { return }
|
|
||||||
fillColor = collectionModel.color
|
|
||||||
isUserInteractionEnabled = collectionModel.enabled ?? true
|
|
||||||
isStrikeThrough = collectionModel.strikethrough ?? false
|
|
||||||
bottomText.text = collectionModel.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
167
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift
Normal file
167
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
//
|
||||||
|
// RadioSwatchItem.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Lekshmi S on 01/04/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
open class RadioSwatchItem: Control {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
public var bottomText = Label.createLabelRegularMicro(true)
|
||||||
|
public var isOutOfStock = false
|
||||||
|
public var fillColor: Color = Color(uiColor: .mvmBlue)
|
||||||
|
|
||||||
|
private var circleLayer: CAShapeLayer?
|
||||||
|
private var selectedLayer: CALayer?
|
||||||
|
private var strikeLayer: CALayer?
|
||||||
|
private var maskLayer: CALayer?
|
||||||
|
|
||||||
|
public var radioSwatchModel: RadioSwatchItemModel? {
|
||||||
|
return model as? RadioSwatchItemModel
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Lifecycle
|
||||||
|
//--------------------------------------------------
|
||||||
|
open override func updateView(_ size: CGFloat) {
|
||||||
|
super.updateView(size)
|
||||||
|
bottomText.updateView(size)
|
||||||
|
layer.setNeedsDisplay()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func setupView() {
|
||||||
|
super.setupView()
|
||||||
|
|
||||||
|
addSubview(bottomText)
|
||||||
|
bottomText.textAlignment = .center
|
||||||
|
bottomText.topAnchor.constraint(equalTo: topAnchor, constant: 38).isActive = true
|
||||||
|
bottomText.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
|
||||||
|
bottomText.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
|
||||||
|
bottomAnchor.constraint(equalTo: bottomText.bottomAnchor).isActive = true
|
||||||
|
addTarget(self, action: #selector(selectSwatch), for: .touchUpInside)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
guard let model = model as? RadioSwatchItemModel else { return }
|
||||||
|
fillColor = model.color
|
||||||
|
isSelected = model.selected ?? false
|
||||||
|
isEnabled = model.enabled ?? true
|
||||||
|
bottomText.text = model.text
|
||||||
|
isOutOfStock = model.strikethrough ?? false
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// MARK: - State Handling
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
open override func draw(_ layer: CALayer, in ctx: CGContext) {
|
||||||
|
//Draw the swatch
|
||||||
|
circleLayer?.removeFromSuperlayer()
|
||||||
|
let circle = getCircle(color: UIColor.mvmBlack, thickness: 1)
|
||||||
|
layer.addSublayer(circle)
|
||||||
|
circleLayer = circle
|
||||||
|
|
||||||
|
//Draw the strikethrough
|
||||||
|
strikeLayer?.removeFromSuperlayer()
|
||||||
|
if isOutOfStock {
|
||||||
|
let line = getStrikeThrough(color: UIColor.mvmCoolGray6, thickness: 1)
|
||||||
|
layer.addSublayer(line)
|
||||||
|
strikeLayer = line
|
||||||
|
}
|
||||||
|
|
||||||
|
//Draw the selected layer
|
||||||
|
selectedLayer?.removeFromSuperlayer()
|
||||||
|
if isSelected {
|
||||||
|
let outerCircle = getSelectedLayer(color: UIColor.black, thickness: 1)
|
||||||
|
layer.addSublayer(outerCircle)
|
||||||
|
selectedLayer = outerCircle
|
||||||
|
bottomText.isHidden = false
|
||||||
|
} else {
|
||||||
|
circleLayer?.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath
|
||||||
|
bottomText.isHidden = true
|
||||||
|
}
|
||||||
|
|
||||||
|
//Handle Mask
|
||||||
|
maskLayer?.removeFromSuperlayer()
|
||||||
|
if !isEnabled {
|
||||||
|
let mask = getMaskLayer()
|
||||||
|
layer.mask = mask
|
||||||
|
maskLayer = mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
// Accounts for any size changes
|
||||||
|
layer.setNeedsDisplay()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc open func selectSwatch() {
|
||||||
|
isSelected = true
|
||||||
|
radioSwatchModel?.selected = isSelected
|
||||||
|
layer.setNeedsDisplay()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc open func deselectSwatch() {
|
||||||
|
isSelected = false
|
||||||
|
radioSwatchModel?.selected = isSelected
|
||||||
|
layer.setNeedsDisplay()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCircle(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
|
||||||
|
let circle = CAShapeLayer()
|
||||||
|
circle.name = "innercircle"
|
||||||
|
circle.fillColor = fillColor.cgColor
|
||||||
|
circle.opacity = 1.0
|
||||||
|
circle.lineWidth = thickness
|
||||||
|
circle.strokeColor = isEnabled ? color.cgColor : UIColor.mvmCoolGray6.cgColor
|
||||||
|
|
||||||
|
let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30))
|
||||||
|
circle.path = circlePath.cgPath
|
||||||
|
return circle
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStrikeThrough(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
|
||||||
|
let strikeThrough = CAShapeLayer()
|
||||||
|
strikeThrough.name = "strikethrough"
|
||||||
|
strikeThrough.fillColor = nil
|
||||||
|
strikeThrough.opacity = 1.0
|
||||||
|
strikeThrough.lineWidth = thickness
|
||||||
|
strikeThrough.strokeColor = color.cgColor
|
||||||
|
|
||||||
|
let linePath = UIBezierPath()
|
||||||
|
linePath.move(to: CGPoint(x: 12, y: 30))
|
||||||
|
linePath.addLine(to: CGPoint(x: 42, y: 0))
|
||||||
|
strikeThrough.path = linePath.cgPath
|
||||||
|
return strikeThrough
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSelectedLayer(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
|
||||||
|
circleLayer?.path = UIBezierPath(ovalIn: CGRect(x: 15, y: 4, width: 24, height: 24)).cgPath
|
||||||
|
let circle = CAShapeLayer()
|
||||||
|
circle.name = "outercircle"
|
||||||
|
circle.fillColor = UIColor.clear.cgColor
|
||||||
|
circle.opacity = 1.0
|
||||||
|
circle.lineWidth = thickness
|
||||||
|
circle.strokeColor = color.cgColor
|
||||||
|
|
||||||
|
let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30))
|
||||||
|
circle.path = circlePath.cgPath
|
||||||
|
return circle
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMaskLayer() -> CALayer {
|
||||||
|
let mask = CALayer()
|
||||||
|
mask.backgroundColor = UIColor.white.cgColor
|
||||||
|
mask.opacity = 0.3
|
||||||
|
mask.frame = bounds
|
||||||
|
return mask
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// RadioSwatchItemCollectionViewCell.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Lekshmi S on 13/04/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
open class RadioSwatchItemCollectionViewCell: CollectionViewCell {
|
||||||
|
let radioSwatch = RadioSwatchItem()
|
||||||
|
|
||||||
|
open override func setupView() {
|
||||||
|
super.setupView()
|
||||||
|
addMolecule(radioSwatch)
|
||||||
|
MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
|
guard let model = model as? RadioSwatchItemModel else { return }
|
||||||
|
radioSwatch.set(with: model, delegateObject, additionalData)
|
||||||
|
self.isUserInteractionEnabled = model.enabled ?? true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,97 +6,97 @@
|
|||||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import Foundation
|
||||||
|
|
||||||
open class RadioSwatches: View {
|
open class RadioSwatches: View {
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
public let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
|
public var collectionView: CollectionView!
|
||||||
var swatches: [RadioSwatchItemModel]?
|
var swatches: [RadioSwatchItemModel]?
|
||||||
|
private var size: CGFloat?
|
||||||
public var selectedSwatchItem: RadioSwatchItemModel? {
|
private var delegateObject: MVMCoreUIDelegateObject?
|
||||||
get{
|
|
||||||
guard let selectedItem = collectionView.indexPathsForSelectedItems?.first else {return nil}
|
|
||||||
return swatches?[selectedItem.item]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
// MARK: - Constraints
|
// MARK: - Constraints
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
public var collectionViewHeight: NSLayoutConstraint?
|
public var collectionViewHeight: NSLayoutConstraint?
|
||||||
public let cellSize: Double = 54.0
|
private let cellSize: CGFloat = 54.0
|
||||||
public let spacing: Double = 10
|
private let itemSpacing: CGFloat = 8.0
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Lifecycle
|
// MARK: - Lifecycle
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
open override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
// Accounts for any collection size changes
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.collectionView.collectionViewLayout.invalidateLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open override func setupView() {
|
open override func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
guard collectionView.superview == nil else {
|
collectionView = createCollectionView()
|
||||||
return
|
|
||||||
}
|
|
||||||
collectionView.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
collectionView.dataSource = self
|
|
||||||
collectionView.delegate = self
|
|
||||||
collectionView.showsHorizontalScrollIndicator = false
|
|
||||||
collectionView.backgroundColor = .clear
|
|
||||||
collectionView.isAccessibilityElement = false
|
|
||||||
addSubview(collectionView)
|
addSubview(collectionView)
|
||||||
NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)
|
NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)
|
||||||
collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 100)
|
collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 100)
|
||||||
collectionViewHeight?.isActive = true
|
collectionViewHeight?.isActive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func updateView(_ size: CGFloat) {
|
@objc override open func updateView(_ size: CGFloat) {
|
||||||
DispatchQueue.main.async {
|
super.updateView(size)
|
||||||
self.collectionView.collectionViewLayout.invalidateLayout()
|
self.size = size
|
||||||
self.collectionView.reloadData()
|
collectionView.updateView(size)
|
||||||
guard let selectedCell = self.swatches?.firstIndex(where: {$0.selected == true}) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.collectionView.selectItem(at: IndexPath(item: selectedCell, section: 0), animated: true, scrollPosition: .centeredHorizontally)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
super.set(with: model, delegateObject, additionalData)
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
self.delegateObject = delegateObject
|
||||||
|
|
||||||
guard let radioSwatchesModel = model as? RadioSwatchesModel else { return }
|
guard let radioSwatchesModel = model as? RadioSwatchesModel else { return }
|
||||||
collectionView.layer.borderColor = backgroundColor?.cgColor
|
swatches = radioSwatchesModel.swatches
|
||||||
|
FormValidator.setupValidation(for: radioSwatchesModel, delegate: delegateObject?.formHolderDelegate)
|
||||||
registerCells()
|
registerCells()
|
||||||
setupLayout(with: radioSwatchesModel)
|
setHeight()
|
||||||
prepareMolecules(with: radioSwatchesModel)
|
|
||||||
collectionView.reloadData()
|
collectionView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
// MARK: - Methods
|
// MARK: - Methods
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
func registerCells() {
|
open func registerCells() {
|
||||||
collectionView.register(RadioSwatchItem.self, forCellWithReuseIdentifier: "RadioSwatchItemCollectionViewCell")
|
collectionView.register(RadioSwatchItemCollectionViewCell.self, forCellWithReuseIdentifier: "RadioSwatchItemCollectionViewCell")
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupLayout(with radioSwatchesModel: RadioSwatchesModel?) {
|
/// Creates the collection view.
|
||||||
|
open func createCollectionView() -> CollectionView {
|
||||||
|
let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout())
|
||||||
|
collection.dataSource = self
|
||||||
|
collection.delegate = self
|
||||||
|
return collection
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates the layout for the collection.
|
||||||
|
open func createCollectionViewLayout() -> UICollectionViewLayout {
|
||||||
let layout = UICollectionViewFlowLayout()
|
let layout = UICollectionViewFlowLayout()
|
||||||
layout.scrollDirection = .vertical
|
layout.scrollDirection = .vertical
|
||||||
layout.minimumLineSpacing = CGFloat(spacing)
|
layout.minimumLineSpacing = itemSpacing
|
||||||
layout.minimumInteritemSpacing = CGFloat(spacing)
|
layout.minimumInteritemSpacing = itemSpacing
|
||||||
collectionView.collectionViewLayout = layout
|
return layout
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareMolecules(with radioSwatchesModel: RadioSwatchesModel?) {
|
open func setHeight() {
|
||||||
guard let newSwatches = radioSwatchesModel?.swatches else {
|
guard let swatches = swatches, swatches.count > 0 else {
|
||||||
swatches = nil
|
collectionViewHeight?.constant = 0
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
swatches = newSwatches
|
// Calculate the height
|
||||||
let collectionViewWidth = UIScreen.main.bounds.width - (2 * MFStyler.defaultHorizontalPaddingForApplicationWidth())
|
let collectionViewWidth = UIScreen.main.bounds.width - (2 * MFStyler.defaultHorizontalPaddingForApplicationWidth())
|
||||||
let swatchesInRow = Double(floor(Double(collectionViewWidth/60.0)))
|
let swatchesInRow = floor(CGFloat(collectionViewWidth/(cellSize + itemSpacing)))
|
||||||
let numberOfRows = floor(Double(swatches?.count ?? 1)/swatchesInRow) + 1.0
|
let numberOfRows = ceil(CGFloat(swatches.count)/swatchesInRow)
|
||||||
let height = (numberOfRows * cellSize) + (spacing * (numberOfRows-1))
|
let height = (numberOfRows * cellSize) + (itemSpacing * (numberOfRows-1))
|
||||||
collectionViewHeight?.constant = CGFloat(height)
|
collectionViewHeight?.constant = CGFloat(height)
|
||||||
collectionViewHeight?.isActive = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,21 +115,28 @@ extension RadioSwatches: UICollectionViewDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchItemCollectionViewCell", for: indexPath) as? RadioSwatchItem else {
|
guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchItemCollectionViewCell", for: indexPath) as? RadioSwatchItemCollectionViewCell else {
|
||||||
return UICollectionViewCell()
|
fatalError()
|
||||||
}
|
}
|
||||||
cell.set(with: molecule, nil, nil)
|
cell.radioSwatch.isUserInteractionEnabled = false
|
||||||
|
cell.set(with: molecule, delegateObject, nil)
|
||||||
|
cell.updateView(size ?? collectionView.bounds.width)
|
||||||
|
if molecule.selected ?? false {
|
||||||
|
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
|
||||||
|
}
|
||||||
|
cell.layoutIfNeeded()
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension RadioSwatches: UICollectionViewDelegate {
|
extension RadioSwatches: UICollectionViewDelegate {
|
||||||
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
guard let swatchItem = swatches?[indexPath.row] else { return }
|
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return }
|
||||||
swatchItem.selected = true
|
cell.radioSwatch.selectSwatch()
|
||||||
|
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||||
}
|
}
|
||||||
public func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
public func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
||||||
guard let swatchItem = swatches?[indexPath.row] else { return }
|
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return }
|
||||||
swatchItem.selected = false
|
cell.radioSwatch.deselectSwatch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8,25 +8,39 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol {
|
@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||||
public var backgroundColor: Color?
|
public var backgroundColor: Color?
|
||||||
public static var identifier: String = "radioSwatches"
|
public static var identifier: String = "radioSwatches"
|
||||||
public var swatches: [RadioSwatchItemModel]
|
public var swatches: [RadioSwatchItemModel]
|
||||||
|
public var fieldKey: String?
|
||||||
|
public var groupName: String = FormValidator.defaultGroupName
|
||||||
|
public var baseValue: AnyHashable?
|
||||||
|
|
||||||
public init(swatches: [RadioSwatchItemModel]) {
|
/// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch.
|
||||||
self.swatches = swatches
|
public func formFieldValue() -> AnyHashable? {
|
||||||
|
let selectedSwatch = swatches.first { (swatch) -> Bool in
|
||||||
|
return (swatch.selected ?? false)
|
||||||
|
}
|
||||||
|
return selectedSwatch?.fieldValue ?? selectedSwatch?.text
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case moleculeName
|
case moleculeName
|
||||||
case backgroundColor
|
case backgroundColor
|
||||||
case swatches
|
case swatches
|
||||||
|
case fieldKey
|
||||||
|
case groupName
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
self.swatches = try typeContainer.decode([RadioSwatchItemModel].self, forKey: .swatches)
|
|
||||||
self.backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
self.backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||||
|
self.swatches = try typeContainer.decode([RadioSwatchItemModel].self, forKey: .swatches)
|
||||||
|
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||||
|
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||||
|
self.groupName = groupName
|
||||||
|
}
|
||||||
|
baseValue = formFieldValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
@ -34,10 +48,12 @@ import Foundation
|
|||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||||
try container.encode(swatches, forKey: .swatches)
|
try container.encode(swatches, forKey: .swatches)
|
||||||
|
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||||
|
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objcMembers public class RadioSwatchItemModel: MoleculeModelProtocol, FormFieldProtocol {
|
@objcMembers public class RadioSwatchItemModel: MoleculeModelProtocol {
|
||||||
public var backgroundColor: Color?
|
public var backgroundColor: Color?
|
||||||
public static var identifier: String = "radioSwatchItem"
|
public static var identifier: String = "radioSwatchItem"
|
||||||
public var color: Color = Color(uiColor: .mvmBlue)
|
public var color: Color = Color(uiColor: .mvmBlue)
|
||||||
@ -47,24 +63,6 @@ import Foundation
|
|||||||
public var strikethrough: Bool? = false
|
public var strikethrough: Bool? = false
|
||||||
public var fieldKey: String?
|
public var fieldKey: String?
|
||||||
public var fieldValue: String?
|
public var fieldValue: String?
|
||||||
public var baseValue: AnyHashable?
|
|
||||||
public var groupName: String = FormValidator.defaultGroupName
|
|
||||||
|
|
||||||
public init(color: Color, text:String, selected: Bool, enabled: Bool, strikethrough: Bool, fieldKey: String, fieldValue: String, groupName:String) {
|
|
||||||
self.color = color
|
|
||||||
self.text = text
|
|
||||||
self.selected = selected
|
|
||||||
self.fieldValue = fieldValue
|
|
||||||
self.enabled = enabled
|
|
||||||
self.strikethrough = strikethrough
|
|
||||||
self.fieldKey = fieldKey
|
|
||||||
self.groupName = groupName
|
|
||||||
baseValue = selected
|
|
||||||
}
|
|
||||||
|
|
||||||
public func formFieldValue() -> AnyHashable? {
|
|
||||||
return selected
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case moleculeName
|
case moleculeName
|
||||||
@ -74,9 +72,7 @@ import Foundation
|
|||||||
case selected
|
case selected
|
||||||
case enabled
|
case enabled
|
||||||
case strikethrough
|
case strikethrough
|
||||||
case fieldKey
|
|
||||||
case fieldValue
|
case fieldValue
|
||||||
case groupName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
@ -95,12 +91,7 @@ import Foundation
|
|||||||
if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
|
if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
|
||||||
self.strikethrough = strikethrough
|
self.strikethrough = strikethrough
|
||||||
}
|
}
|
||||||
baseValue = self.selected
|
|
||||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
|
||||||
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
|
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
|
||||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
|
||||||
self.groupName = groupName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
@ -112,9 +103,7 @@ import Foundation
|
|||||||
try container.encodeIfPresent(selected, forKey: .selected)
|
try container.encodeIfPresent(selected, forKey: .selected)
|
||||||
try container.encodeIfPresent(enabled, forKey: .enabled)
|
try container.encodeIfPresent(enabled, forKey: .enabled)
|
||||||
try container.encodeIfPresent(strikethrough, forKey: .strikethrough)
|
try container.encodeIfPresent(strikethrough, forKey: .strikethrough)
|
||||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
|
||||||
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
||||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +70,7 @@ import Foundation
|
|||||||
MoleculeObjectMapping.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self)
|
||||||
MoleculeObjectMapping.shared()?.register(viewClass: RadioBoxes.self, viewModelClass: RadioBoxesModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: RadioBoxes.self, viewModelClass: RadioBoxesModel.self)
|
||||||
MoleculeObjectMapping.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self)
|
||||||
|
MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatches.self, viewModelClass: RadioSwatchesModel.self)
|
||||||
|
|
||||||
// Other Atoms
|
// Other Atoms
|
||||||
MoleculeObjectMapping.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user