From 8a796467e66ea0d3c90bbe0236e7e200b1d10602 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 4 Dec 2019 15:50:08 -0500 Subject: [PATCH 01/59] Initial state of Swiftified Switch. --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + MVMCoreUI/Atoms/Views/Switch.swift | 376 ++++++++++++++++++++++++++++ 2 files changed, 380 insertions(+) create mode 100644 MVMCoreUI/Atoms/Views/Switch.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 900edec2..33529648 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; + 0AA33B3A2398524F0067DD0F /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Switch.swift */; }; 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; @@ -226,6 +227,7 @@ 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; + 0AA33B392398524F0067DD0F /* Switch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = ""; }; 943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = ""; }; 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; @@ -779,6 +781,7 @@ 01004F2F22721C3800991ECC /* RadioButton.swift */, 943784F3236B77BB006A1E82 /* GraphView.swift */, 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */, + 0AA33B392398524F0067DD0F /* Switch.swift */, ); path = Views; sourceTree = ""; @@ -1082,6 +1085,7 @@ D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */, D2B18B7F2360913400A9AEDC /* Control.swift in Sources */, + 0AA33B3A2398524F0067DD0F /* Switch.swift in Sources */, D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */, DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */, D224798C231450C8003FCCF9 /* HeadlineBodySwitch.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Switch.swift new file mode 100644 index 00000000..d7e9b25e --- /dev/null +++ b/MVMCoreUI/Atoms/Views/Switch.swift @@ -0,0 +1,376 @@ +// +// Switch.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 12/4/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import MVMCore +import MVMCoreUI +import UIKit + +typealias ValueChangeBlock = () -> Void + +open class Switch: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { + var on = false + var onTintColor: UIColor? + var offTintColor: UIColor? + var onKnobTintColor: UIColor? + var offKnobTintColor: UIColor? + var shouldTouchToSwitch = false + var valueChangedBlock: ValueChangeBlock? + var actionBlock: ValueChangeBlock? + + let SwitchWidth: CGFloat = 42 + let SwitchHeight: CGFloat = 22 + let SwitchKnobWidth: CGFloat = 20 + let SwitchKnobHeight: CGFloat = 20 + let SwitchShakeIntensity: CGFloat = 2 + + private weak var baseView: UIView? + private weak var knobView: UIView? + private var knobLeftConstraint: NSLayoutConstraint? + private var knobRightConstraint: NSLayoutConstraint? + private var knobHeightConstraint: NSLayoutConstraint? + private var knobWidthConstraint: NSLayoutConstraint? + private weak var height: NSLayoutConstraint? + private weak var width: NSLayoutConstraint? + private var valueShouldChange = false + private var canChangeValue = false + private var json: [AnyHashable: Any]? + private var delegate: DelegateObject? + + public func updateView(_ size: CGFloat) { + height?.constant = MVMCoreUISwitch.getHeight() + width?.constant = MVMCoreUISwitch.getWidth() + baseView?.layer.cornerRadius = MVMCoreUISwitch.getHeight() / 2.0 + knobView?.layer.cornerRadius = MVMCoreUISwitch.getKnobHeight() * 0.5 + knobHeightConstraint?.constant = MVMCoreUISwitch.getKnobHeight() + knobWidthConstraint?.constant = MVMCoreUISwitch.getKnobWidth() + } + + public func setupView() { + onTintColor = UIColor.mfSwitchOnTint() + offTintColor = UIColor.mfSwitchOffTint() + canChangeValue = true + shouldTouchToSwitch = true + setUpViewWithState(on) + accessibilityLabel() = MVMCoreUIUtility.hardcodedString(withKey: "MVMCoreUISwitch_buttonlabel") + } + + public required init?(coder: NSCoder) { + if super.init(coder: coder) != nil { + setupView() + } + } + + public init(frame: CGRect) { + if super.init(frame: frame) != nil { + setupView() + } + } + + public init() { + if super.init() { + setupView() + } + } + + public class func mvmSwitchDefault() -> Self { + let mySwitch = self.init(frame: CGRect.zero) + mySwitch?.translatesAutoresizingMaskIntoConstraints = false + return mySwitch + } + + public class func mvmSwitchDefault(with block: ValueChangeBlock?) -> Self { + let mySwitch = self.init(frame: CGRect.zero) + mySwitch?.valueChangedBlock = block + return mySwitch + } + + public func setUpViewWithState(_ on: Bool) { + if !self.baseView { + isUserInteractionEnabled = true + valueShouldChange = true + + let baseView = MVMCoreUICommonViewsUtility.commonView() + if let baseView = baseView { + addSubview(baseView) + } + NSLayoutConstraint.constraintPinSubview(toSuperview: baseView) + let constraints = NSLayoutConstraint.constraintPinView(baseView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getWidth()) + self.height = constraints.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) + self.width = constraints.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) + baseView?.layer.cornerRadius = MVMCoreUISwitch.getHeight() / 2.0 + + onKnobTintColor = UIColor.white + offKnobTintColor = UIColor.white + + let knobView = MVMCoreUICommonViewsUtility.commonView() + knobView?.backgroundColor = UIColor.white + knobView?.layer.cornerRadius = MVMCoreUISwitch.getKnobHeight() * 0.5 + if let knobView = knobView { + baseView?.addSubview(knobView) + } + let heightWidth = NSLayoutConstraint.constraintPinView(knobView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getKnobHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getKnobWidth()) + let height = heightWidth.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) + let width = heightWidth.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) + knobHeightConstraint = height + knobWidthConstraint = width + let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(knobView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) + + let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(knobView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) + let `left` = leadingTrailingDic.object(forKey: ConstraintLeading, ofType: NSLayoutConstraint.self) + let `right` = leadingTrailingDic.object(forKey: ConstraintTrailing, ofType: NSLayoutConstraint.self) + NSLayoutConstraint.constraintPinSubview(knobView, pinCenterX: false, centerXConstant: 0, pinCenterY: true, centerYConstant: 0) + `right`?.constant = 15 + knobLeftConstraint = `left` + knobRightConstraint = `right` + baseView.bringSubviewToFront(knobView) + + //baseView = baseView // Skipping redundant initializing to itself + //knobView = knobView // Skipping redundant initializing to itself + + baseView.isUserInteractionEnabled = false + knobView.isUserInteractionEnabled = false + shouldTouchToSwitch = false + setState(on, animated: false) + shouldTouchToSwitch = true + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + self.json = json + delegate = delegateObject + + FormValidator.setupValidation(withMolecule: self, delegate: delegateObject?.formValidationProtocol) + + var color = json?.string("onTintColor") + if color != nil { + onTintColor = UIColor.mfGet(forHex: color) + } + + color = json?.string("offTintColor") + if color != nil { + offTintColor = UIColor.mfGet(forHex: color) + } + + color = json?.string("onKnobTintColor") + if color != nil { + onKnobTintColor = UIColor.mfGet(forHex: color) + } + + color = json?.string("offKnobTintColor") + if color != nil { + offKnobTintColor = UIColor.mfGet(forHex: color) + } + + setState(json?.bool(forKey: "state"), animated: false) + + let actionMap = json?.dict("actionMap") + if actionMap != nil { + addTarget(self, action: #selector(addCustomAction), for: .touchUpInside) + } + } + + public @objc func addCustomAction() { + if actionBlock { + actionBlock() + } + } + + public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return self.getSwitchHeight() + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + public func needsToBeConstrained() -> Bool { + return true + } + + public func alignment() -> UIStackView.Alignment { + return .trailing + } + + // MARK: - UIResponder overide + public func touchesBegan(_ touches: Set, with event: UIEvent) { + knobEnlargeAnimation() + sendActions(for: .touchDown) + } + + public func touchesEnded(_ touches: Set, with event: UIEvent) { + if shouldTouchToSwitch { + if valueShouldChange { + changeValue() + } + } + sendActions(for: .touchUpInside) + knobMoveAnitmationTo(on: isOn) + knobShakeAnitmationTo(on: isOn) + knobReformAnimation(true) + valueShouldChange = true + } + + public func touchesMoved(_ touches: Set, with event: UIEvent) { + if shouldTouchToSwitch { + if touchMoves(toLeft: touches) { + knobMoveAnitmationTo(on: false) + knobShakeAnitmationTo(on: false) + knobReformAnimation(true) + } else { + knobMoveAnitmationTo(on: true) + knobShakeAnitmationTo(on: true) + knobReformAnimation(true) + } + } + if touchIsOutSide(touches) { + sendActions(for: .touchDragOutside) + if !shouldTouchToSwitch { + knobReformAnimation(true) + } + } else { + sendActions(for: .touchDragInside) + } + } + + public func touchesCancelled(_ touches: Set, with event: UIEvent) { + if shouldTouchToSwitch { + knobReformAnimation(true) + canChangeValue = true + } + sendActions(for: .touchCancel) + } + + // MARK: - animation + public func knobEnlargeAnimation() { + UIView.animate(withDuration: 0.1, animations: { + self.knobWidthConstraint.constant += PaddingOne + self.layoutIfNeeded() + }) + } + + public func knobReformAnimation(_ animated: Bool) { + if animated { + UIView.animate(withDuration: 0.1, animations: { + self.knobWidthConstraint.constant = MVMCoreUISwitch.getKnobWidth() + self.layoutIfNeeded() + }) { finished in + } + } else { + knobWidthConstraint.constant = MVMCoreUISwitch.getKnobWidth() + layoutIfNeeded() + } + } + + public func knobMoveAnitmationTo(on toOn: Bool) { + UIView.animate(withDuration: 0.1, animations: { + if toOn { + self.knobLeftConstraint.priority = 1 + self.knobRightConstraint.priority = 999 + self.knobRightConstraint.constant = 1 + } else { + self.knobLeftConstraint.priority = 999 + self.knobRightConstraint.priority = 1 + self.knobLeftConstraint.constant = 1 + } + self.setBaseColorToOn(toOn, animated: true) + self.knobWidthConstraint.constant = MVMCoreUISwitch.getKnobWidth() + PaddingOne + self.valueShouldChange = toOn != self.on + self.layoutIfNeeded() + }) + } + + public func setBaseColorToOn(_ toOn: Bool, animated: Bool) { + if animated { + UIView.beginAnimations(nil, context: nil) + UIView.setAnimationDuration(0.2) + UIView.setAnimationCurve(.easeIn) + if toOn { + knobView.backgroundColor = onKnobTintColor + baseView.backgroundColor = onTintColor + } else { + knobView.backgroundColor = offKnobTintColor + baseView.backgroundColor = offTintColor + } + UIView.commitAnimations() + } else if on { + knobView.backgroundColor = onKnobTintColor + baseView.backgroundColor = onTintColor + } else { + knobView.backgroundColor = offKnobTintColor + baseView.backgroundColor = offTintColor + } + } + + //used after knob moving to match the behavior of default uiswitch + public func knobShakeAnitmationTo(on toOn: Bool) { + UIView.animate(withDuration: 0.1, delay: 0.1, options: .curveEaseIn, animations: { + if toOn { + self.knobRightConstraint.constant = SwitchShakeIntensity + } else { + self.knobLeftConstraint.constant = SwitchShakeIntensity + } + self.layoutIfNeeded() + }) { finished in + } + UIView.animate(withDuration: 0.2, delay: 0.1, options: [], animations: { + if toOn { + self.knobRightConstraint.constant = 1 + } else { + self.knobLeftConstraint.constant = 1 + } + self.layoutIfNeeded() + }) { finished in + self.valueShouldChange = true + } + } + + // MARK: - switch logic + public func setState(_ state: Bool, animated: Bool) { + setState(state, withoutBlockAnimated: animated) + if valueChangedBlock { + valueChangedBlock() + } + + if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged.formValidatorModel)) { + let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged.formValidatorModel)) as? FormValidator + formValidator?.enableByValidation() + } + } + + public func setState(_ state: Bool, withoutBlockAnimated animated: Bool) { + on = state + if !shouldTouchToSwitch { + knobEnlargeAnimation() + knobMoveAnitmationTo(on: on) + knobShakeAnitmationTo(on: on) + } + if on { + knobLeftConstraint.priority = 1 + knobRightConstraint.priority = 999 + knobRightConstraint.constant = 1 + } else { + knobRightConstraint.priority = 1 + knobLeftConstraint.priority = 999 + knobLeftConstraint.constant = 1 + } + + setBaseColorToOn(on, animated: animated) + knobReformAnimation(animated) + accessibilityValue = state ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") + setNeedsLayout() + layoutIfNeeded() + } + + public func changeValue() -> Bool { + on ^= true + shouldTouchToSwitch = false + setState(on, animated: true) + shouldTouchToSwitch = true + sendActions(for: .valueChanged) + return on + } + } +} + From a00fdbad6041289fef25710bb3f2b2535d7fed7a Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 5 Dec 2019 15:16:46 -0500 Subject: [PATCH 02/59] Grooming process in converting objc to swift with Switch. --- MVMCoreUI/Atoms/Views/Switch.swift | 709 ++++++++++++++++------------ MVMCoreUI/BaseClasses/Control.swift | 5 +- 2 files changed, 406 insertions(+), 308 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Switch.swift index d7e9b25e..e12fd890 100644 --- a/MVMCoreUI/Atoms/Views/Switch.swift +++ b/MVMCoreUI/Atoms/Views/Switch.swift @@ -10,367 +10,464 @@ import MVMCore import MVMCoreUI import UIKit -typealias ValueChangeBlock = () -> Void +typealias ValueChangeBlock = () -> () -open class Switch: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { - var on = false - var onTintColor: UIColor? - var offTintColor: UIColor? - var onKnobTintColor: UIColor? - var offKnobTintColor: UIColor? +open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public var isOn = false + public var trackTintColor: (on: UIColor?, off: UIColor?)? + public var thumbTintColor: (on: UIColor?, off: UIColor?)? + var shouldTouchToSwitch = false var valueChangedBlock: ValueChangeBlock? var actionBlock: ValueChangeBlock? - let SwitchWidth: CGFloat = 42 - let SwitchHeight: CGFloat = 22 - let SwitchKnobWidth: CGFloat = 20 - let SwitchKnobHeight: CGFloat = 20 - let SwitchShakeIntensity: CGFloat = 2 + static let width: CGFloat = 42 + static let height: CGFloat = 22 + static let thumbWidth: CGFloat = 20 + static let thumbHeight: CGFloat = 20 + static let shakeIntensity: CGFloat = 2 private weak var baseView: UIView? - private weak var knobView: UIView? - private var knobLeftConstraint: NSLayoutConstraint? - private var knobRightConstraint: NSLayoutConstraint? - private var knobHeightConstraint: NSLayoutConstraint? - private var knobWidthConstraint: NSLayoutConstraint? - private weak var height: NSLayoutConstraint? - private weak var width: NSLayoutConstraint? + private weak var thumbView: UIView? + private var valueShouldChange = false private var canChangeValue = false - private var json: [AnyHashable: Any]? + + //-------------------------------------------------- + // MARK: - Delegate + //-------------------------------------------------- + private var delegate: DelegateObject? + //-------------------------------------------------- + // MARK: - Constraints + //-------------------------------------------------- + + private var thumbLeftConstraint: NSLayoutConstraint? + private var thumbRightConstraint: NSLayoutConstraint? + private var thumbHeightConstraint: NSLayoutConstraint? + private var thumbWidthConstraint: NSLayoutConstraint? + private weak var height: NSLayoutConstraint? + private weak var width: NSLayoutConstraint? + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + public func updateView(_ size: CGFloat) { + height?.constant = MVMCoreUISwitch.getHeight() width?.constant = MVMCoreUISwitch.getWidth() baseView?.layer.cornerRadius = MVMCoreUISwitch.getHeight() / 2.0 - knobView?.layer.cornerRadius = MVMCoreUISwitch.getKnobHeight() * 0.5 - knobHeightConstraint?.constant = MVMCoreUISwitch.getKnobHeight() - knobWidthConstraint?.constant = MVMCoreUISwitch.getKnobWidth() + thumbView?.layer.cornerRadius = MVMCoreUISwitch.getthumbHeight() * 0.5 + thumbHeightConstraint?.constant = MVMCoreUISwitch.getthumbHeight() + thumbWidthConstraint?.constant = MVMCoreUISwitch.getthumbWidth() } public func setupView() { - onTintColor = UIColor.mfSwitchOnTint() - offTintColor = UIColor.mfSwitchOffTint() + + trackTintColor?.on = .mfSwitchOnTint() + trackTintColor?.off = .mfSwitchOffTint() canChangeValue = true shouldTouchToSwitch = true - setUpViewWithState(on) - accessibilityLabel() = MVMCoreUIUtility.hardcodedString(withKey: "MVMCoreUISwitch_buttonlabel") + setUpViewWithState(isOn) + accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "MVMCoreUISwitch_buttonlabel") + } + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + + public override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + public convenience init() { + self.init(frame: frame) } public required init?(coder: NSCoder) { - if super.init(coder: coder) != nil { - setupView() - } + super.init(coder: coder) + fatalError("Switch does not support xib") } - public init(frame: CGRect) { - if super.init(frame: frame) != nil { - setupView() - } - } - - public init() { - if super.init() { - setupView() - } - } + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- public class func mvmSwitchDefault() -> Self { - let mySwitch = self.init(frame: CGRect.zero) + + let mySwitch = self.init(frame: .zero) mySwitch?.translatesAutoresizingMaskIntoConstraints = false return mySwitch } public class func mvmSwitchDefault(with block: ValueChangeBlock?) -> Self { - let mySwitch = self.init(frame: CGRect.zero) + + let mySwitch = self.init(frame: .zero) mySwitch?.valueChangedBlock = block return mySwitch } public func setUpViewWithState(_ on: Bool) { - if !self.baseView { - isUserInteractionEnabled = true - valueShouldChange = true - - let baseView = MVMCoreUICommonViewsUtility.commonView() - if let baseView = baseView { - addSubview(baseView) - } - NSLayoutConstraint.constraintPinSubview(toSuperview: baseView) - let constraints = NSLayoutConstraint.constraintPinView(baseView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getWidth()) - self.height = constraints.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) - self.width = constraints.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) - baseView?.layer.cornerRadius = MVMCoreUISwitch.getHeight() / 2.0 - - onKnobTintColor = UIColor.white - offKnobTintColor = UIColor.white - - let knobView = MVMCoreUICommonViewsUtility.commonView() - knobView?.backgroundColor = UIColor.white - knobView?.layer.cornerRadius = MVMCoreUISwitch.getKnobHeight() * 0.5 - if let knobView = knobView { - baseView?.addSubview(knobView) - } - let heightWidth = NSLayoutConstraint.constraintPinView(knobView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getKnobHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getKnobWidth()) - let height = heightWidth.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) - let width = heightWidth.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) - knobHeightConstraint = height - knobWidthConstraint = width - let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(knobView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) - - let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(knobView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) - let `left` = leadingTrailingDic.object(forKey: ConstraintLeading, ofType: NSLayoutConstraint.self) - let `right` = leadingTrailingDic.object(forKey: ConstraintTrailing, ofType: NSLayoutConstraint.self) - NSLayoutConstraint.constraintPinSubview(knobView, pinCenterX: false, centerXConstant: 0, pinCenterY: true, centerYConstant: 0) - `right`?.constant = 15 - knobLeftConstraint = `left` - knobRightConstraint = `right` - baseView.bringSubviewToFront(knobView) - - //baseView = baseView // Skipping redundant initializing to itself - //knobView = knobView // Skipping redundant initializing to itself - - baseView.isUserInteractionEnabled = false - knobView.isUserInteractionEnabled = false - shouldTouchToSwitch = false - setState(on, animated: false) - shouldTouchToSwitch = true + + guard baseView == nil else { return } + + isUserInteractionEnabled = true + valueShouldChange = true + + let baseView = MVMCoreUICommonViewsUtility.commonView() + + if let baseView = baseView { + addSubview(baseView) } - // MARK: - MVMCoreUIMoleculeViewProtocol - public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - self.json = json - delegate = delegateObject - - FormValidator.setupValidation(withMolecule: self, delegate: delegateObject?.formValidationProtocol) - - var color = json?.string("onTintColor") - if color != nil { - onTintColor = UIColor.mfGet(forHex: color) - } - - color = json?.string("offTintColor") - if color != nil { - offTintColor = UIColor.mfGet(forHex: color) - } - - color = json?.string("onKnobTintColor") - if color != nil { - onKnobTintColor = UIColor.mfGet(forHex: color) - } - - color = json?.string("offKnobTintColor") - if color != nil { - offKnobTintColor = UIColor.mfGet(forHex: color) - } - - setState(json?.bool(forKey: "state"), animated: false) - - let actionMap = json?.dict("actionMap") - if actionMap != nil { - addTarget(self, action: #selector(addCustomAction), for: .touchUpInside) - } + NSLayoutConstraint.constraintPinSubview(toSuperview: baseView) + let constraints = NSLayoutConstraint.constraintPinView(baseView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getWidth()) + self.height = constraints.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) + self.width = constraints.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) + baseView?.layer.cornerRadius = MVMCoreUISwitch.getHeight() / 2.0 + + onthumbTintColor = UIColor.white + offthumbTintColor = UIColor.white + + let thumbView = MVMCoreUICommonViewsUtility.commonView() + thumbView?.backgroundColor = UIColor.white + thumbView?.layer.cornerRadius = MVMCoreUISwitch.getthumbHeight() * 0.5 + + if let thumbView = thumbView { + baseView?.addSubview(thumbView) } - public @objc func addCustomAction() { - if actionBlock { - actionBlock() - } + let heightWidth = NSLayoutConstraint.constraintPinView(thumbView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getthumbHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getthumbWidth()) + let height = heightWidth.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) + let width = heightWidth.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) + thumbHeightConstraint = height + thumbWidthConstraint = width + let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(thumbView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) + + let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(thumbView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) + let `left` = leadingTrailingDic.object(forKey: ConstraintLeading, ofType: NSLayoutConstraint.self) + let `right` = leadingTrailingDic.object(forKey: ConstraintTrailing, ofType: NSLayoutConstraint.self) + NSLayoutConstraint.constraintPinSubview(thumbView, pinCenterX: false, centerXConstant: 0, pinCenterY: true, centerYConstant: 0) + `right`?.constant = 15 + thumbLeftConstraint = `left` + thumbRightConstraint = `right` + baseView.bringSubviewToFront(thumbView) + + //baseView = baseView // Skipping redundant initializing to itself + //thumbView = thumbView // Skipping redundant initializing to itself + + baseView.isUserInteractionEnabled = false + thumbView.isUserInteractionEnabled = false + shouldTouchToSwitch = false + setState(on, animated: false) + shouldTouchToSwitch = true + } + + @objc func addCustomAction() { + + actionBlock?() + } + + public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + + return Switch.getSwitchHeight() + } + + // MARK: - UIResponder overide + public func touchesBegan(_ touches: Set, with event: UIEvent) { + + thumbEnlargeAnimation() + sendActions(for: .touchDown) + } + + public func touchesEnded(_ touches: Set, with event: UIEvent) { + + if shouldTouchToSwitch && valueShouldChange{ + changeValue() } - public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - return self.getSwitchHeight() - } + sendActions(for: .touchUpInside) + thumbMoveAnitmationTo(on: isOn) + thumbShakeAnitmationTo(on: isOn) + thumbReformAnimation(true) + valueShouldChange = true + } + + public func touchesMoved(_ touches: Set, with event: UIEvent) { - // MARK: - MVMCoreUIMoleculeViewProtocol - public func needsToBeConstrained() -> Bool { - return true - } - - public func alignment() -> UIStackView.Alignment { - return .trailing - } - - // MARK: - UIResponder overide - public func touchesBegan(_ touches: Set, with event: UIEvent) { - knobEnlargeAnimation() - sendActions(for: .touchDown) - } - - public func touchesEnded(_ touches: Set, with event: UIEvent) { - if shouldTouchToSwitch { - if valueShouldChange { - changeValue() - } - } - sendActions(for: .touchUpInside) - knobMoveAnitmationTo(on: isOn) - knobShakeAnitmationTo(on: isOn) - knobReformAnimation(true) - valueShouldChange = true - } - - public func touchesMoved(_ touches: Set, with event: UIEvent) { - if shouldTouchToSwitch { - if touchMoves(toLeft: touches) { - knobMoveAnitmationTo(on: false) - knobShakeAnitmationTo(on: false) - knobReformAnimation(true) - } else { - knobMoveAnitmationTo(on: true) - knobShakeAnitmationTo(on: true) - knobReformAnimation(true) - } - } - if touchIsOutSide(touches) { - sendActions(for: .touchDragOutside) - if !shouldTouchToSwitch { - knobReformAnimation(true) - } + if shouldTouchToSwitch { + if touchMoves(toLeft: touches) { + thumbMoveAnitmationTo(on: false) + thumbShakeAnitmationTo(on: false) + thumbReformAnimation(true) } else { - sendActions(for: .touchDragInside) + thumbMoveAnitmationTo(on: true) + thumbShakeAnitmationTo(on: true) + thumbReformAnimation(true) } } - public func touchesCancelled(_ touches: Set, with event: UIEvent) { - if shouldTouchToSwitch { - knobReformAnimation(true) - canChangeValue = true - } - sendActions(for: .touchCancel) - } - - // MARK: - animation - public func knobEnlargeAnimation() { - UIView.animate(withDuration: 0.1, animations: { - self.knobWidthConstraint.constant += PaddingOne - self.layoutIfNeeded() - }) - } - - public func knobReformAnimation(_ animated: Bool) { - if animated { - UIView.animate(withDuration: 0.1, animations: { - self.knobWidthConstraint.constant = MVMCoreUISwitch.getKnobWidth() - self.layoutIfNeeded() - }) { finished in - } - } else { - knobWidthConstraint.constant = MVMCoreUISwitch.getKnobWidth() - layoutIfNeeded() - } - } - - public func knobMoveAnitmationTo(on toOn: Bool) { - UIView.animate(withDuration: 0.1, animations: { - if toOn { - self.knobLeftConstraint.priority = 1 - self.knobRightConstraint.priority = 999 - self.knobRightConstraint.constant = 1 - } else { - self.knobLeftConstraint.priority = 999 - self.knobRightConstraint.priority = 1 - self.knobLeftConstraint.constant = 1 - } - self.setBaseColorToOn(toOn, animated: true) - self.knobWidthConstraint.constant = MVMCoreUISwitch.getKnobWidth() + PaddingOne - self.valueShouldChange = toOn != self.on - self.layoutIfNeeded() - }) - } - - public func setBaseColorToOn(_ toOn: Bool, animated: Bool) { - if animated { - UIView.beginAnimations(nil, context: nil) - UIView.setAnimationDuration(0.2) - UIView.setAnimationCurve(.easeIn) - if toOn { - knobView.backgroundColor = onKnobTintColor - baseView.backgroundColor = onTintColor - } else { - knobView.backgroundColor = offKnobTintColor - baseView.backgroundColor = offTintColor - } - UIView.commitAnimations() - } else if on { - knobView.backgroundColor = onKnobTintColor - baseView.backgroundColor = onTintColor - } else { - knobView.backgroundColor = offKnobTintColor - baseView.backgroundColor = offTintColor - } - } - - //used after knob moving to match the behavior of default uiswitch - public func knobShakeAnitmationTo(on toOn: Bool) { - UIView.animate(withDuration: 0.1, delay: 0.1, options: .curveEaseIn, animations: { - if toOn { - self.knobRightConstraint.constant = SwitchShakeIntensity - } else { - self.knobLeftConstraint.constant = SwitchShakeIntensity - } - self.layoutIfNeeded() - }) { finished in - } - UIView.animate(withDuration: 0.2, delay: 0.1, options: [], animations: { - if toOn { - self.knobRightConstraint.constant = 1 - } else { - self.knobLeftConstraint.constant = 1 - } - self.layoutIfNeeded() - }) { finished in - self.valueShouldChange = true - } - } - - // MARK: - switch logic - public func setState(_ state: Bool, animated: Bool) { - setState(state, withoutBlockAnimated: animated) - if valueChangedBlock { - valueChangedBlock() - } - - if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged.formValidatorModel)) { - let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged.formValidatorModel)) as? FormValidator - formValidator?.enableByValidation() - } - } - - public func setState(_ state: Bool, withoutBlockAnimated animated: Bool) { - on = state + if touchIsOutSide(touches) { + sendActions(for: .touchDragOutside) if !shouldTouchToSwitch { - knobEnlargeAnimation() - knobMoveAnitmationTo(on: on) - knobShakeAnitmationTo(on: on) + thumbReformAnimation(true) } - if on { - knobLeftConstraint.priority = 1 - knobRightConstraint.priority = 999 - knobRightConstraint.constant = 1 - } else { - knobRightConstraint.priority = 1 - knobLeftConstraint.priority = 999 - knobLeftConstraint.constant = 1 + } else { + sendActions(for: .touchDragInside) + } + } + + public func touchesCancelled(_ touches: Set, with event: UIEvent) { + + if shouldTouchToSwitch { + thumbReformAnimation(true) + canChangeValue = true + } + + sendActions(for: .touchCancel) + } + + // MARK: - animation + public func thumbEnlargeAnimation() { + + UIView.animate(withDuration: 0.1, animations: { + self.thumbWidthConstraint?.constant += PaddingOne + self.layoutIfNeeded() + }) + } + + public func thumbReformAnimation(_ animated: Bool) { + + if animated { + UIView.animate(withDuration: 0.1, animations: { + self.thumbWidthConstraint?.constant = MVMCoreUISwitch.getthumbWidth() + self.layoutIfNeeded() + }) { finished in } - - setBaseColorToOn(on, animated: animated) - knobReformAnimation(animated) - accessibilityValue = state ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") - setNeedsLayout() + } else { + thumbWidthConstraint?.constant = MVMCoreUISwitch.getthumbWidth() layoutIfNeeded() } + } + + public func thumbMoveAnitmationTo(on toOn: Bool) { - public func changeValue() -> Bool { - on ^= true - shouldTouchToSwitch = false - setState(on, animated: true) - shouldTouchToSwitch = true - sendActions(for: .valueChanged) - return on + UIView.animate(withDuration: 0.1, animations: { + if toOn { + self.thumbLeftConstraint?.priority = UILayoutPriority(1) + self.thumbRightConstraint?.priority = UILayoutPriority(999) + self.thumbRightConstraint?.constant = 1 + } else { + self.thumbLeftConstraint?.priority = UILayoutPriority(999) + self.thumbRightConstraint?.priority = UILayoutPriority(1) + self.thumbLeftConstraint?.constant = 1 + } + self.setBaseColorToOn(toOn, animated: true) + self.thumbWidthConstraint?.constant = MVMCoreUISwitch.getThumbWidth() + PaddingOne + self.valueShouldChange = toOn != self.isOn + self.layoutIfNeeded() + }) + } + + public func setBaseColorToOn(_ toOn: Bool, animated: Bool) { + + if animated { + UIView.beginAnimations(nil, context: nil) + UIView.setAnimationDuration(0.2) + UIView.setAnimationCurve(.easeIn) + + if toOn { + thumbView?.backgroundColor = thumbTintColor!.on + baseView?.backgroundColor = trackTintColor!.on + } else { + thumbView?.backgroundColor = thumbTintColor!.off + baseView?.backgroundColor = trackTintColor!.off + } + UIView.commitAnimations() + } else if isOn { + thumbView?.backgroundColor = thumbTintColor!.on + baseView?.backgroundColor = trackTintColor!.on + } else { + thumbView?.backgroundColor = thumbTintColor!.off + baseView?.backgroundColor = trackTintColor!.off } } + + //used after thumb moving to match the behavior of default uiswitch + public func thumbShakeAnitmationTo(on toOn: Bool) { + UIView.animate(withDuration: 0.1, delay: 0.1, options: .curveEaseIn, animations: { + if toOn { + self.thumbRightConstraint?.constant = Switch.shakeIntensity + } else { + self.thumbLeftConstraint?.constant = Switch.shakeIntensity + } + self.layoutIfNeeded() + }) { finished in + } + UIView.animate(withDuration: 0.2, delay: 0.1, options: [], animations: { + if toOn { + self.thumbRightConstraint?.constant = 1 + } else { + self.thumbLeftConstraint?.constant = 1 + } + self.layoutIfNeeded() + }) { finished in + self.valueShouldChange = true + } + } + + public func setState(_ state: Bool, animated: Bool) { + setState(state, withoutBlockAnimated: animated) + + valueChangedBlock?() + + if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged.formValidatorModel)) { + let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged.formValidatorModel)) as? FormValidator + formValidator?.enableByValidation() + } + } + + public func setState(_ state: Bool, withoutBlockAnimated animated: Bool) { + + isOn = state + + if !shouldTouchToSwitch { + thumbEnlargeAnimation() + thumbMoveAnitmationTo(on: isOn) + thumbShakeAnitmationTo(on: isOn) + } + + if isOn { + thumbLeftConstraint?.priority = UILayoutPriority(1) + thumbRightConstraint?.priority = UILayoutPriority(999) + thumbRightConstraint?.constant = 1 + } else { + thumbRightConstraint?.priority = UILayoutPriority(1) + thumbLeftConstraint?.priority = UILayoutPriority(999) + thumbLeftConstraint?.constant = 1 + } + + setBaseColorToOn(isOn, animated: animated) + thumbReformAnimation(animated) + accessibilityValue = state ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") + setNeedsLayout() + layoutIfNeeded() + } + + public func changeValue() -> Bool { + isOn ^= true + shouldTouchToSwitch = false + setState(isOn, animated: true) + shouldTouchToSwitch = true + sendActions(for: .valueChanged) + return isOn + } + + + // MARK: - helper + func touchIsOutSide(_ touches: Set?) -> Bool { + + let location = touches?.first?.location(in: self) + let x = Float(location?.x ?? 0.0) + let y = Float(location?.y ?? 0.0) + return x < 0 || x > frame.size.width || y < 0 || y > frame.size.height + } + + func touchMoves(toLeft touches: Set?) -> Bool { + + let location = touches?.first?.location(in: self) + let x = Float(location?.x ?? 0.0) + return x < frame.size.width / 2.0 + } + + class func getSwitchWidth() -> CGFloat { + return (MFSizeObject(standardSize: Switch.width, standardiPadPortraitSize: Double(SwitchWidth) * 1.5)).getValueBasedOnApplicationWidth() + } + + class func getSwitchHeight() -> CGFloat { + return (MFSizeObject(standardSize: Switch.height, standardiPadPortraitSize: Double(SwitchHeight) * 1.5)).getValueBasedOnApplicationWidth() + } + + class func getSwitchthumbWidth() -> CGFloat { + return (MFSizeObject(standardSize: Switch.thumbWidth, standardiPadPortraitSize: Double(SwitchthumbWidth) * 1.5)).getValueBasedOnApplicationWidth() + } + + class func getSwitchthumbHeight() -> CGFloat { + return (MFSizeObject(standardSize: Switch.thumbHeight, standardiPadPortraitSize: Double(SwitchthumbHeight) * 1.5)).getValueBasedOnApplicationWidth() + } } +// MARK: - Accessibility +extension Switch { + + func formFieldGroupName() -> String? { + return json.string("groupName") + } +} + +// MARK: FormValidationProtocol +extension Switch { + + func isValidField() -> Bool { + return isOn && json.bool(forKey: "required") + } + + func formFieldName() -> String? { + return json.string(KeyFieldKey) + } + + func formFieldValue() -> Any? { + return NSNumber(value: isOn) + } +} + +// MARK: - MVMCoreUIMoleculeViewProtocol +extension Switch: MVMCoreUIMoleculeViewProtocol { + + public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + self.json = json + delegate = delegateObject + + guard let dictionary = json else { return } + + FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) + + if let color = dictionary["onTintColor"] as? String { + trackTintColor?.on = UIColor.mfGet(forHex: color) + } + + if let color = dictionary["offTintColor"] as? String { + trackTintColor?.off = UIColor.mfGet(forHex: color) + } + + if let color = dictionary["onthumbTintColor"] as? String { + thumbTintColor?.on = UIColor.mfGet(forHex: color) + } + + if let color = dictionary["offthumbTintColor"] as? String { + thumbTintColor?.off = UIColor.mfGet(forHex: color) + } + + setState(json?.bool(forKey: "state"), animated: false) + + let actionMap = json?.dict("actionMap") + if actionMap != nil { + addTarget(self, action: #selector(addCustomAction), for: .touchUpInside) + } + } + + public func needsToBeConstrained() -> Bool { + return true + } + + public func alignment() -> UIStackView.Alignment { + return .trailing + } +} diff --git a/MVMCoreUI/BaseClasses/Control.swift b/MVMCoreUI/BaseClasses/Control.swift index fdf8204f..e1690306 100644 --- a/MVMCoreUI/BaseClasses/Control.swift +++ b/MVMCoreUI/BaseClasses/Control.swift @@ -9,6 +9,7 @@ import UIKit public class Control: UIControl { + var json: [AnyHashable: Any]? private var initialSetupPerformed = false @@ -37,8 +38,8 @@ public class Control: UIControl { } extension Control: MVMCoreViewProtocol { - public func updateView(_ size: CGFloat) { - } + + public func updateView(_ size: CGFloat) { } /// Will be called only once. public func setupView() { From cbb016406a5b6463119fc5ef90e185fee2400845 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 9 Dec 2019 13:37:33 -0500 Subject: [PATCH 03/59] WIP, putting Switch together. --- MVMCoreUI/Atoms/Views/Switch.swift | 377 +++++++++--------- MVMCoreUI/BaseClasses/Control.swift | 19 +- .../MVMCoreUIMoleculeMappingObject.m | 2 +- 3 files changed, 212 insertions(+), 186 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Switch.swift index e12fd890..025c7b64 100644 --- a/MVMCoreUI/Atoms/Views/Switch.swift +++ b/MVMCoreUI/Atoms/Views/Switch.swift @@ -7,17 +7,16 @@ // import MVMCore -import MVMCoreUI import UIKit -typealias ValueChangeBlock = () -> () +public typealias ValueChangeBlock = () -> () -open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { + +@objcMembers open class Switch: Control, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public var isOn = false public var trackTintColor: (on: UIColor?, off: UIColor?)? public var thumbTintColor: (on: UIColor?, off: UIColor?)? @@ -25,18 +24,40 @@ open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtoc var valueChangedBlock: ValueChangeBlock? var actionBlock: ValueChangeBlock? - static let width: CGFloat = 42 - static let height: CGFloat = 22 - static let thumbWidth: CGFloat = 20 - static let thumbHeight: CGFloat = 20 + static let trackSize = CGSize(width: 46, height: 24) + static let thumbSize = CGSize(width: 22, height: 22) + static let shakeIntensity: CGFloat = 2 - private weak var baseView: UIView? - private weak var thumbView: UIView? + private var thumbView = View() private var valueShouldChange = false private var canChangeValue = false + //-------------------------------------------------- + // MARK: - Computed Properties + //-------------------------------------------------- + + open override var isEnabled: Bool { + didSet { + if isEnabled { + + } else { + + } + } + } + + open var isOn: Bool = false { + didSet { + if isOn { + + } else { + + } + } + } + //-------------------------------------------------- // MARK: - Delegate //-------------------------------------------------- @@ -47,36 +68,12 @@ open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtoc // MARK: - Constraints //-------------------------------------------------- - private var thumbLeftConstraint: NSLayoutConstraint? - private var thumbRightConstraint: NSLayoutConstraint? + private var thumbLeadingConstraint: NSLayoutConstraint? + private var thumbTrailingConstraint: NSLayoutConstraint? private var thumbHeightConstraint: NSLayoutConstraint? private var thumbWidthConstraint: NSLayoutConstraint? - private weak var height: NSLayoutConstraint? - private weak var width: NSLayoutConstraint? - - //-------------------------------------------------- - // MARK: - Lifecycle - //-------------------------------------------------- - - public func updateView(_ size: CGFloat) { - - height?.constant = MVMCoreUISwitch.getHeight() - width?.constant = MVMCoreUISwitch.getWidth() - baseView?.layer.cornerRadius = MVMCoreUISwitch.getHeight() / 2.0 - thumbView?.layer.cornerRadius = MVMCoreUISwitch.getthumbHeight() * 0.5 - thumbHeightConstraint?.constant = MVMCoreUISwitch.getthumbHeight() - thumbWidthConstraint?.constant = MVMCoreUISwitch.getthumbWidth() - } - - public func setupView() { - - trackTintColor?.on = .mfSwitchOnTint() - trackTintColor?.off = .mfSwitchOffTint() - canChangeValue = true - shouldTouchToSwitch = true - setUpViewWithState(isOn) - accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "MVMCoreUISwitch_buttonlabel") - } + private var heightConstraint: NSLayoutConstraint? + private var widthConstraint: NSLayoutConstraint? //-------------------------------------------------- // MARK: - Initializers @@ -87,100 +84,101 @@ open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtoc setupView() } - public convenience init() { + public convenience override init() { self.init(frame: frame) } + public convenience init(isOn: Bool, changeBlock: ValueChangeBlock?) { + self.init(frame: frame) + self.isOn = isOn + valueChangedBlock = changeBlock + } + + public convenience init(changeBlock: ValueChangeBlock?) { + self.init(frame: frame) + valueChangedBlock = changeBlock + } + public required init?(coder: NSCoder) { super.init(coder: coder) - fatalError("Switch does not support xib") + fatalError("Switch does not support xib.") + } + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + public override func updateView(_ size: CGFloat) { + super.updateView(size) + + heightConstraint?.constant = Switch.getTrackHeight() + widthConstraint?.constant = Switch.getTrackWidth() + + layer.cornerRadius = Switch.getTrackHeight() / 2.0 + thumbView.layer.cornerRadius = Switch.getThumbHeight() / 2.0 + + thumbHeightConstraint?.constant = Switch.getThumbHeight() + thumbWidthConstraint?.constant = Switch.getThumbWidth() + } + + public override func setupView() { + super.setupView() + + guard !subviews.isEmpty else { return } + + trackTintColor?.on = .mfSwitchOnTint() // Green + trackTintColor?.off = .mfSwitchOffTint() // Black + + thumbTintColor?.on = .white + thumbTintColor?.off = .white + + canChangeValue = true + shouldTouchToSwitch = true + valueShouldChange = true + + heightConstraint = heightAnchor.constraint(equalToConstant: Switch.trackSize.height) + heightConstraint?.isActive = true + + widthConstraint = widthAnchor.constraint(equalToConstant: Switch.trackSize.width) + widthConstraint?.isActive = true + + layer.cornerRadius = Switch.trackSize.height / 2.0 + + let thumbView = MVMCoreUICommonViewsUtility.commonView() + thumbView.backgroundColor = .white + thumbView.layer.cornerRadius = Switch.getThumbHeight() / 2.0 + + addSubview(thumbView) + + thumbView.heightAnchor.constraint(equalToConstant: Switch.thumbSize.height).isActive = true + thumbView.widthAnchor.constraint(equalToConstant: Switch.thumbSize.width).isActive = true + thumbView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + + thumbTrailingConstraint = trailingAnchor.constraint(equalTo: thumbView.trailingAnchor, constant: 1) + thumbLeadingConstraint = thumbView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1) + thumbLeadingConstraint?.isActive = true + + shouldTouchToSwitch = false + setState(isOn, animated: false) + shouldTouchToSwitch = true + + accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Switch_buttonlabel") } //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- - public class func mvmSwitchDefault() -> Self { - - let mySwitch = self.init(frame: .zero) - mySwitch?.translatesAutoresizingMaskIntoConstraints = false - return mySwitch - } - - public class func mvmSwitchDefault(with block: ValueChangeBlock?) -> Self { - - let mySwitch = self.init(frame: .zero) - mySwitch?.valueChangedBlock = block - return mySwitch - } - - public func setUpViewWithState(_ on: Bool) { - - guard baseView == nil else { return } - - isUserInteractionEnabled = true - valueShouldChange = true - - let baseView = MVMCoreUICommonViewsUtility.commonView() - - if let baseView = baseView { - addSubview(baseView) - } - - NSLayoutConstraint.constraintPinSubview(toSuperview: baseView) - let constraints = NSLayoutConstraint.constraintPinView(baseView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getWidth()) - self.height = constraints.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) - self.width = constraints.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) - baseView?.layer.cornerRadius = MVMCoreUISwitch.getHeight() / 2.0 - - onthumbTintColor = UIColor.white - offthumbTintColor = UIColor.white - - let thumbView = MVMCoreUICommonViewsUtility.commonView() - thumbView?.backgroundColor = UIColor.white - thumbView?.layer.cornerRadius = MVMCoreUISwitch.getthumbHeight() * 0.5 - - if let thumbView = thumbView { - baseView?.addSubview(thumbView) - } - - let heightWidth = NSLayoutConstraint.constraintPinView(thumbView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getthumbHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getthumbWidth()) - let height = heightWidth.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) - let width = heightWidth.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) - thumbHeightConstraint = height - thumbWidthConstraint = width - let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(thumbView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) - - let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(thumbView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) - let `left` = leadingTrailingDic.object(forKey: ConstraintLeading, ofType: NSLayoutConstraint.self) - let `right` = leadingTrailingDic.object(forKey: ConstraintTrailing, ofType: NSLayoutConstraint.self) - NSLayoutConstraint.constraintPinSubview(thumbView, pinCenterX: false, centerXConstant: 0, pinCenterY: true, centerYConstant: 0) - `right`?.constant = 15 - thumbLeftConstraint = `left` - thumbRightConstraint = `right` - baseView.bringSubviewToFront(thumbView) - - //baseView = baseView // Skipping redundant initializing to itself - //thumbView = thumbView // Skipping redundant initializing to itself - - baseView.isUserInteractionEnabled = false - thumbView.isUserInteractionEnabled = false - shouldTouchToSwitch = false - setState(on, animated: false) - shouldTouchToSwitch = true - } - @objc func addCustomAction() { actionBlock?() } - public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - - return Switch.getSwitchHeight() - } - // MARK: - UIResponder overide + //-------------------------------------------------- + // MARK: - UIResponder + //-------------------------------------------------- + public func touchesBegan(_ touches: Set, with event: UIEvent) { thumbEnlargeAnimation() @@ -189,7 +187,7 @@ open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtoc public func touchesEnded(_ touches: Set, with event: UIEvent) { - if shouldTouchToSwitch && valueShouldChange{ + if shouldTouchToSwitch && valueShouldChange { changeValue() } @@ -247,12 +245,11 @@ open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtoc if animated { UIView.animate(withDuration: 0.1, animations: { - self.thumbWidthConstraint?.constant = MVMCoreUISwitch.getthumbWidth() + self.thumbWidthConstraint?.constant = Switch.getThumbWidth() self.layoutIfNeeded() - }) { finished in - } + }) { finished in } } else { - thumbWidthConstraint?.constant = MVMCoreUISwitch.getthumbWidth() + thumbWidthConstraint?.constant = Switch.getThumbWidth() layoutIfNeeded() } } @@ -261,16 +258,18 @@ open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtoc UIView.animate(withDuration: 0.1, animations: { if toOn { - self.thumbLeftConstraint?.priority = UILayoutPriority(1) - self.thumbRightConstraint?.priority = UILayoutPriority(999) - self.thumbRightConstraint?.constant = 1 + self.thumbLeadingConstraint?.priority = UILayoutPriority(1) + self.thumbTrailingConstraint?.priority = UILayoutPriority(999) + self.thumbTrailingConstraint?.constant = 1 + } else { - self.thumbLeftConstraint?.priority = UILayoutPriority(999) - self.thumbRightConstraint?.priority = UILayoutPriority(1) - self.thumbLeftConstraint?.constant = 1 + self.thumbLeadingConstraint?.priority = UILayoutPriority(999) + self.thumbTrailingConstraint?.priority = UILayoutPriority(1) + self.thumbLeadingConstraint?.constant = 1 } + self.setBaseColorToOn(toOn, animated: true) - self.thumbWidthConstraint?.constant = MVMCoreUISwitch.getThumbWidth() + PaddingOne + self.thumbWidthConstraint?.constant = Switch.getThumbWidth() + PaddingOne self.valueShouldChange = toOn != self.isOn self.layoutIfNeeded() }) @@ -284,38 +283,41 @@ open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtoc UIView.setAnimationCurve(.easeIn) if toOn { - thumbView?.backgroundColor = thumbTintColor!.on - baseView?.backgroundColor = trackTintColor!.on + thumbView.backgroundColor = thumbTintColor?.on + backgroundColor = trackTintColor?.on } else { - thumbView?.backgroundColor = thumbTintColor!.off - baseView?.backgroundColor = trackTintColor!.off + thumbView.backgroundColor = thumbTintColor?.off + backgroundColor = trackTintColor?.off } UIView.commitAnimations() + } else if isOn { - thumbView?.backgroundColor = thumbTintColor!.on - baseView?.backgroundColor = trackTintColor!.on + thumbView.backgroundColor = thumbTintColor?.on + backgroundColor = trackTintColor?.on + } else { - thumbView?.backgroundColor = thumbTintColor!.off - baseView?.backgroundColor = trackTintColor!.off + thumbView.backgroundColor = thumbTintColor?.off + backgroundColor = trackTintColor?.off } } //used after thumb moving to match the behavior of default uiswitch public func thumbShakeAnitmationTo(on toOn: Bool) { + UIView.animate(withDuration: 0.1, delay: 0.1, options: .curveEaseIn, animations: { if toOn { - self.thumbRightConstraint?.constant = Switch.shakeIntensity + self.thumbTrailingConstraint?.constant = Switch.shakeIntensity } else { - self.thumbLeftConstraint?.constant = Switch.shakeIntensity + self.thumbLeadingConstraint?.constant = Switch.shakeIntensity } self.layoutIfNeeded() - }) { finished in - } + }, completion: nil) + UIView.animate(withDuration: 0.2, delay: 0.1, options: [], animations: { if toOn { - self.thumbRightConstraint?.constant = 1 + self.thumbTrailingConstraint?.constant = 1 } else { - self.thumbLeftConstraint?.constant = 1 + self.thumbLeadingConstraint?.constant = 1 } self.layoutIfNeeded() }) { finished in @@ -328,10 +330,10 @@ open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtoc valueChangedBlock?() - if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged.formValidatorModel)) { - let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged.formValidatorModel)) as? FormValidator - formValidator?.enableByValidation() - } + // if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged.formValidatorModel)) { + let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged.formValidatorModel)) as? FormValidator + formValidator?.enableByValidation() + // } } public func setState(_ state: Bool, withoutBlockAnimated animated: Bool) { @@ -345,13 +347,13 @@ open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtoc } if isOn { - thumbLeftConstraint?.priority = UILayoutPriority(1) - thumbRightConstraint?.priority = UILayoutPriority(999) - thumbRightConstraint?.constant = 1 + thumbLeadingConstraint?.priority = UILayoutPriority(1) + thumbTrailingConstraint?.priority = UILayoutPriority(999) + thumbTrailingConstraint?.constant = 1 } else { - thumbRightConstraint?.priority = UILayoutPriority(1) - thumbLeftConstraint?.priority = UILayoutPriority(999) - thumbLeftConstraint?.constant = 1 + thumbTrailingConstraint?.priority = UILayoutPriority(1) + thumbLeadingConstraint?.priority = UILayoutPriority(999) + thumbLeadingConstraint?.constant = 1 } setBaseColorToOn(isOn, animated: animated) @@ -361,77 +363,82 @@ open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtoc layoutIfNeeded() } + @discardableResult public func changeValue() -> Bool { - isOn ^= true + + isOn.toggle() shouldTouchToSwitch = false setState(isOn, animated: true) shouldTouchToSwitch = true sendActions(for: .valueChanged) - return isOn - } - - - // MARK: - helper - func touchIsOutSide(_ touches: Set?) -> Bool { - let location = touches?.first?.location(in: self) - let x = Float(location?.x ?? 0.0) - let y = Float(location?.y ?? 0.0) - return x < 0 || x > frame.size.width || y < 0 || y > frame.size.height + return isOn } func touchMoves(toLeft touches: Set?) -> Bool { let location = touches?.first?.location(in: self) - let x = Float(location?.x ?? 0.0) + let x = CGFloat(location?.x ?? 0.0) return x < frame.size.width / 2.0 } - class func getSwitchWidth() -> CGFloat { - return (MFSizeObject(standardSize: Switch.width, standardiPadPortraitSize: Double(SwitchWidth) * 1.5)).getValueBasedOnApplicationWidth() + override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + + let faultTolerance: CGFloat = 20.0 + let area = bounds.insetBy(dx: -faultTolerance, dy: -faultTolerance) + return area.contains(point) } - class func getSwitchHeight() -> CGFloat { - return (MFSizeObject(standardSize: Switch.height, standardiPadPortraitSize: Double(SwitchHeight) * 1.5)).getValueBasedOnApplicationWidth() + open override func touchesEnded(_ touches: Set, with event: UIEvent?) { + + sendActions(for: .touchUpInside) } - class func getSwitchthumbWidth() -> CGFloat { - return (MFSizeObject(standardSize: Switch.thumbWidth, standardiPadPortraitSize: Double(SwitchthumbWidth) * 1.5)).getValueBasedOnApplicationWidth() + class func getTrackWidth() -> CGFloat { + return (MFSizeObject(standardSize: Switch.trackSize.width, standardiPadPortraitSize: CGFloat(Switch.trackSize.width * 1.5)))!.getValueBasedOnApplicationWidth() } - class func getSwitchthumbHeight() -> CGFloat { - return (MFSizeObject(standardSize: Switch.thumbHeight, standardiPadPortraitSize: Double(SwitchthumbHeight) * 1.5)).getValueBasedOnApplicationWidth() + class func getTrackHeight() -> CGFloat { + return (MFSizeObject(standardSize: Switch.trackSize.height, standardiPadPortraitSize: CGFloat(Switch.trackSize.height * 1.5) ))!.getValueBasedOnApplicationWidth() + } + + class func getThumbWidth() -> CGFloat { + return (MFSizeObject(standardSize: Switch.thumbSize.width, standardiPadPortraitSize: CGFloat(Switch.thumbSize.width * 1.5)))!.getValueBasedOnApplicationWidth() + } + + class func getThumbHeight() -> CGFloat { + return (MFSizeObject(standardSize: Switch.thumbSize.height, standardiPadPortraitSize: CGFloat(Switch.thumbSize.height * 1.5)))!.getValueBasedOnApplicationWidth() } } // MARK: - Accessibility extension Switch { - func formFieldGroupName() -> String? { - return json.string("groupName") + public func formFieldGroupName() -> String? { + return json?["groupName"] as? String } } // MARK: FormValidationProtocol extension Switch { - func isValidField() -> Bool { - return isOn && json.bool(forKey: "required") + public func isValidField() -> Bool { + return isOn && json?["required"] as? Bool ?? false } - func formFieldName() -> String? { - return json.string(KeyFieldKey) + public func formFieldName() -> String? { + return json?[KeyFieldKey] as? String ?? "" } - func formFieldValue() -> Any? { + public func formFieldValue() -> Any? { return NSNumber(value: isOn) } } // MARK: - MVMCoreUIMoleculeViewProtocol -extension Switch: MVMCoreUIMoleculeViewProtocol { +extension Switch { - public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + public override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { self.json = json delegate = delegateObject @@ -455,14 +462,18 @@ extension Switch: MVMCoreUIMoleculeViewProtocol { thumbTintColor?.off = UIColor.mfGet(forHex: color) } - setState(json?.bool(forKey: "state"), animated: false) + setState(dictionary["state"] as? Bool ?? false, animated: false) - let actionMap = json?.dict("actionMap") - if actionMap != nil { + if let _ = dictionary["actionMap"] as? [String: Any] { addTarget(self, action: #selector(addCustomAction), for: .touchUpInside) } } + public class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + + return Switch.getTrackHeight() + } + public func needsToBeConstrained() -> Bool { return true } diff --git a/MVMCoreUI/BaseClasses/Control.swift b/MVMCoreUI/BaseClasses/Control.swift index e1690306..34785ce1 100644 --- a/MVMCoreUI/BaseClasses/Control.swift +++ b/MVMCoreUI/BaseClasses/Control.swift @@ -8,12 +8,19 @@ import UIKit -public class Control: UIControl { +open class Control: UIControl { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- var json: [AnyHashable: Any]? private var initialSetupPerformed = false + //-------------------------------------------------- + // MARK: - Initialiers + //-------------------------------------------------- + public override init(frame: CGRect) { super.init(frame: .zero) initialSetup() @@ -29,7 +36,12 @@ public class Control: UIControl { initialSetup() } + //-------------------------------------------------- + // MARK: - Setup + //-------------------------------------------------- + public func initialSetup() { + if !initialSetupPerformed { initialSetupPerformed = true setupView() @@ -37,6 +49,7 @@ public class Control: UIControl { } } +// MARK: MVMCoreViewProtocol extension Control: MVMCoreViewProtocol { public func updateView(_ size: CGFloat) { } @@ -48,8 +61,10 @@ extension Control: MVMCoreViewProtocol { } } +// MARK: MVMCoreUIMoleculeViewProtocol extension Control: MVMCoreUIMoleculeViewProtocol { - public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + + public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { self.json = json if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) { diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 51a07225..4923f21d 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -48,7 +48,7 @@ @"radioButtonLabel": RadioButtonLabel.class, @"listItem": MoleculeTableViewCell.class, @"accordionListItem": AccordionMoleculeTableViewCell.class, - @"switch": MVMCoreUISwitch.class, + @"switch": Switch.class, @"leftRightLabelView": LeftRightLabelView.class, @"actionDetailWithImage": ActionDetailWithImage.class, @"image": MFLoadImageView.class, From 1668fb8c3235ada04fa4d2c3f2156cb299f08921 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 9 Dec 2019 15:03:53 -0500 Subject: [PATCH 04/59] More Switch development. --- MVMCoreUI/Atoms/Views/Switch.swift | 227 ++++++++++++++--------------- 1 file changed, 111 insertions(+), 116 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Switch.swift index 025c7b64..03724267 100644 --- a/MVMCoreUI/Atoms/Views/Switch.swift +++ b/MVMCoreUI/Atoms/Views/Switch.swift @@ -16,9 +16,10 @@ public typealias ValueChangeBlock = () -> () //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - - public var trackTintColor: (on: UIColor?, off: UIColor?)? - public var thumbTintColor: (on: UIColor?, off: UIColor?)? + + public var trackTintColor: (on: UIColor?, off: UIColor?)? = (on: .mfShamrock(), off: .black) + public var thumbTintColor: (on: UIColor?, off: UIColor?)? = (on: .white, off: .white) + public var disabledTintColor: (track: UIColor?, thumb: UIColor?)? = (track: .mfSilver(), thumb: .white) var shouldTouchToSwitch = false var valueChangedBlock: ValueChangeBlock? @@ -40,21 +41,16 @@ public typealias ValueChangeBlock = () -> () open override var isEnabled: Bool { didSet { - if isEnabled { - - } else { - - } + isUserInteractionEnabled = isEnabled + backgroundColor = isEnabled ? trackTintColor?.on : disabledTintColor?.track + thumbView.backgroundColor = isEnabled ? thumbTintColor?.on : disabledTintColor?.thumb } } open var isOn: Bool = false { didSet { - if isOn { - - } else { - - } + backgroundColor = isOn ? trackTintColor?.on : trackTintColor?.off + thumbView.backgroundColor = isOn ? thumbTintColor?.on : thumbTintColor?.off } } @@ -62,7 +58,7 @@ public typealias ValueChangeBlock = () -> () // MARK: - Delegate //-------------------------------------------------- - private var delegate: DelegateObject? + private var delegateObject: MVMCoreUIDelegateObject? //-------------------------------------------------- // MARK: - Constraints @@ -85,17 +81,17 @@ public typealias ValueChangeBlock = () -> () } public convenience override init() { - self.init(frame: frame) + self.init(frame: .zero) } public convenience init(isOn: Bool, changeBlock: ValueChangeBlock?) { - self.init(frame: frame) + self.init(frame: .zero) self.isOn = isOn valueChangedBlock = changeBlock } public convenience init(changeBlock: ValueChangeBlock?) { - self.init(frame: frame) + self.init(frame: .zero) valueChangedBlock = changeBlock } @@ -126,12 +122,6 @@ public typealias ValueChangeBlock = () -> () guard !subviews.isEmpty else { return } - trackTintColor?.on = .mfSwitchOnTint() // Green - trackTintColor?.off = .mfSwitchOffTint() // Black - - thumbTintColor?.on = .white - thumbTintColor?.off = .white - canChangeValue = true shouldTouchToSwitch = true valueShouldChange = true @@ -165,6 +155,22 @@ public typealias ValueChangeBlock = () -> () accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Switch_buttonlabel") } + class func getTrackWidth() -> CGFloat { + return (MFSizeObject(standardSize: Switch.trackSize.width, standardiPadPortraitSize: CGFloat(Switch.trackSize.width * 1.5)))!.getValueBasedOnApplicationWidth() + } + + class func getTrackHeight() -> CGFloat { + return (MFSizeObject(standardSize: Switch.trackSize.height, standardiPadPortraitSize: CGFloat(Switch.trackSize.height * 1.5) ))!.getValueBasedOnApplicationWidth() + } + + class func getThumbWidth() -> CGFloat { + return (MFSizeObject(standardSize: Switch.thumbSize.width, standardiPadPortraitSize: CGFloat(Switch.thumbSize.width * 1.5)))!.getValueBasedOnApplicationWidth() + } + + class func getThumbHeight() -> CGFloat { + return (MFSizeObject(standardSize: Switch.thumbSize.height, standardiPadPortraitSize: CGFloat(Switch.thumbSize.height * 1.5)))!.getValueBasedOnApplicationWidth() + } + //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- @@ -174,11 +180,64 @@ public typealias ValueChangeBlock = () -> () actionBlock?() } + public func setState(_ state: Bool, animated: Bool) { + + setState(state, withoutBlockAnimated: animated) + valueChangedBlock?() + FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) + } + + public func setState(_ state: Bool, withoutBlockAnimated animated: Bool) { + + isOn = state + + if !shouldTouchToSwitch { + thumbEnlargeAnimation() + thumbMoveAnitmationTo(on: isOn) + thumbShakeAnitmationTo(on: isOn) + } + + if isOn { + thumbLeadingConstraint?.priority = UILayoutPriority(1) + thumbTrailingConstraint?.priority = UILayoutPriority(999) + thumbTrailingConstraint?.constant = 1 + + } else { + thumbTrailingConstraint?.priority = UILayoutPriority(1) + thumbLeadingConstraint?.priority = UILayoutPriority(999) + thumbLeadingConstraint?.constant = 1 + } + + setBaseColorToOn(isOn, animated: animated) + thumbReformAnimation(animated) + accessibilityValue = state ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") + setNeedsLayout() + layoutIfNeeded() + } + + @discardableResult + public func changeValue() -> Bool { + + isOn.toggle() + shouldTouchToSwitch = false + setState(isOn, animated: true) + shouldTouchToSwitch = true + sendActions(for: .valueChanged) + + return isOn + } //-------------------------------------------------- // MARK: - UIResponder //-------------------------------------------------- + override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + + let faultTolerance: CGFloat = 20.0 + let area = bounds.insetBy(dx: -faultTolerance, dy: -faultTolerance) + return area.contains(point) + } + public func touchesBegan(_ touches: Set, with event: UIEvent) { thumbEnlargeAnimation() @@ -198,6 +257,11 @@ public typealias ValueChangeBlock = () -> () valueShouldChange = true } + open override func touchesEnded(_ touches: Set, with event: UIEvent?) { + + sendActions(for: .touchUpInside) + } + public func touchesMoved(_ touches: Set, with event: UIEvent) { if shouldTouchToSwitch { @@ -211,7 +275,7 @@ public typealias ValueChangeBlock = () -> () thumbReformAnimation(true) } } - + /* if touchIsOutSide(touches) { sendActions(for: .touchDragOutside) if !shouldTouchToSwitch { @@ -220,6 +284,14 @@ public typealias ValueChangeBlock = () -> () } else { sendActions(for: .touchDragInside) } + */ + } + + func touchMoves(toLeft touches: Set?) -> Bool { + + let location = touches?.first?.location(in: self) + let x = CGFloat(location?.x ?? 0.0) + return x < frame.size.width / 2.0 } public func touchesCancelled(_ touches: Set, with event: UIEvent) { @@ -232,7 +304,10 @@ public typealias ValueChangeBlock = () -> () sendActions(for: .touchCancel) } - // MARK: - animation + //-------------------------------------------------- + // MARK: - Animation + //-------------------------------------------------- + public func thumbEnlargeAnimation() { UIView.animate(withDuration: 0.1, animations: { @@ -247,7 +322,7 @@ public typealias ValueChangeBlock = () -> () UIView.animate(withDuration: 0.1, animations: { self.thumbWidthConstraint?.constant = Switch.getThumbWidth() self.layoutIfNeeded() - }) { finished in } + }, completion: nil) } else { thumbWidthConstraint?.constant = Switch.getThumbWidth() layoutIfNeeded() @@ -285,6 +360,7 @@ public typealias ValueChangeBlock = () -> () if toOn { thumbView.backgroundColor = thumbTintColor?.on backgroundColor = trackTintColor?.on + } else { thumbView.backgroundColor = thumbTintColor?.off backgroundColor = trackTintColor?.off @@ -310,7 +386,9 @@ public typealias ValueChangeBlock = () -> () } else { self.thumbLeadingConstraint?.constant = Switch.shakeIntensity } + self.layoutIfNeeded() + }, completion: nil) UIView.animate(withDuration: 0.2, delay: 0.1, options: [], animations: { @@ -319,96 +397,13 @@ public typealias ValueChangeBlock = () -> () } else { self.thumbLeadingConstraint?.constant = 1 } + self.layoutIfNeeded() + }) { finished in self.valueShouldChange = true } } - - public func setState(_ state: Bool, animated: Bool) { - setState(state, withoutBlockAnimated: animated) - - valueChangedBlock?() - - // if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged.formValidatorModel)) { - let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged.formValidatorModel)) as? FormValidator - formValidator?.enableByValidation() - // } - } - - public func setState(_ state: Bool, withoutBlockAnimated animated: Bool) { - - isOn = state - - if !shouldTouchToSwitch { - thumbEnlargeAnimation() - thumbMoveAnitmationTo(on: isOn) - thumbShakeAnitmationTo(on: isOn) - } - - if isOn { - thumbLeadingConstraint?.priority = UILayoutPriority(1) - thumbTrailingConstraint?.priority = UILayoutPriority(999) - thumbTrailingConstraint?.constant = 1 - } else { - thumbTrailingConstraint?.priority = UILayoutPriority(1) - thumbLeadingConstraint?.priority = UILayoutPriority(999) - thumbLeadingConstraint?.constant = 1 - } - - setBaseColorToOn(isOn, animated: animated) - thumbReformAnimation(animated) - accessibilityValue = state ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") - setNeedsLayout() - layoutIfNeeded() - } - - @discardableResult - public func changeValue() -> Bool { - - isOn.toggle() - shouldTouchToSwitch = false - setState(isOn, animated: true) - shouldTouchToSwitch = true - sendActions(for: .valueChanged) - - return isOn - } - - func touchMoves(toLeft touches: Set?) -> Bool { - - let location = touches?.first?.location(in: self) - let x = CGFloat(location?.x ?? 0.0) - return x < frame.size.width / 2.0 - } - - override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { - - let faultTolerance: CGFloat = 20.0 - let area = bounds.insetBy(dx: -faultTolerance, dy: -faultTolerance) - return area.contains(point) - } - - open override func touchesEnded(_ touches: Set, with event: UIEvent?) { - - sendActions(for: .touchUpInside) - } - - class func getTrackWidth() -> CGFloat { - return (MFSizeObject(standardSize: Switch.trackSize.width, standardiPadPortraitSize: CGFloat(Switch.trackSize.width * 1.5)))!.getValueBasedOnApplicationWidth() - } - - class func getTrackHeight() -> CGFloat { - return (MFSizeObject(standardSize: Switch.trackSize.height, standardiPadPortraitSize: CGFloat(Switch.trackSize.height * 1.5) ))!.getValueBasedOnApplicationWidth() - } - - class func getThumbWidth() -> CGFloat { - return (MFSizeObject(standardSize: Switch.thumbSize.width, standardiPadPortraitSize: CGFloat(Switch.thumbSize.width * 1.5)))!.getValueBasedOnApplicationWidth() - } - - class func getThumbHeight() -> CGFloat { - return (MFSizeObject(standardSize: Switch.thumbSize.height, standardiPadPortraitSize: CGFloat(Switch.thumbSize.height * 1.5)))!.getValueBasedOnApplicationWidth() - } } // MARK: - Accessibility @@ -438,9 +433,9 @@ extension Switch { // MARK: - MVMCoreUIMoleculeViewProtocol extension Switch { - public override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - self.json = json - delegate = delegateObject + public override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + self.delegateObject = delegateObject guard let dictionary = json else { return } @@ -454,11 +449,11 @@ extension Switch { trackTintColor?.off = UIColor.mfGet(forHex: color) } - if let color = dictionary["onthumbTintColor"] as? String { + if let color = dictionary["onThumbTintColor"] as? String { thumbTintColor?.on = UIColor.mfGet(forHex: color) } - if let color = dictionary["offthumbTintColor"] as? String { + if let color = dictionary["offThumbTintColor"] as? String { thumbTintColor?.off = UIColor.mfGet(forHex: color) } From dd4770706493771679ae1066888a1cb077292284 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 10 Dec 2019 08:54:01 -0500 Subject: [PATCH 05/59] the latest switch. --- MVMCoreUI/Atoms/Views/Switch.swift | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Switch.swift index 03724267..8ea86227 100644 --- a/MVMCoreUI/Atoms/Views/Switch.swift +++ b/MVMCoreUI/Atoms/Views/Switch.swift @@ -11,7 +11,12 @@ import UIKit public typealias ValueChangeBlock = () -> () - +/** + A custom implementation of Apple's UISwitch. + + Track: The background of the switch control. + Thumb: The circular indicator that slides on the track. + */ @objcMembers open class Switch: Control, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { //-------------------------------------------------- // MARK: - Properties @@ -21,10 +26,14 @@ public typealias ValueChangeBlock = () -> () public var thumbTintColor: (on: UIColor?, off: UIColor?)? = (on: .white, off: .white) public var disabledTintColor: (track: UIColor?, thumb: UIColor?)? = (track: .mfSilver(), thumb: .white) - var shouldTouchToSwitch = false - var valueChangedBlock: ValueChangeBlock? - var actionBlock: ValueChangeBlock? + private var valueShouldChange = false + private var canChangeValue = false + private var shouldTouchToSwitch = false + private var valueChangedBlock: ValueChangeBlock? + private var actionBlock: ValueChangeBlock? + + // Sizes are from InVision design specs. static let trackSize = CGSize(width: 46, height: 24) static let thumbSize = CGSize(width: 22, height: 22) @@ -32,9 +41,6 @@ public typealias ValueChangeBlock = () -> () private var thumbView = View() - private var valueShouldChange = false - private var canChangeValue = false - //-------------------------------------------------- // MARK: - Computed Properties //-------------------------------------------------- From 83370956c1b43cdec3a389e23d59d078e43f1993 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 10 Dec 2019 10:34:08 -0500 Subject: [PATCH 06/59] movemt,. --- MVMCoreUI/Atoms/Views/Switch.swift | 34 ++++++++++++------------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Switch.swift index 8ea86227..da2c13bf 100644 --- a/MVMCoreUI/Atoms/Views/Switch.swift +++ b/MVMCoreUI/Atoms/Views/Switch.swift @@ -9,8 +9,6 @@ import MVMCore import UIKit -public typealias ValueChangeBlock = () -> () - /** A custom implementation of Apple's UISwitch. @@ -27,11 +25,11 @@ public typealias ValueChangeBlock = () -> () public var disabledTintColor: (track: UIColor?, thumb: UIColor?)? = (track: .mfSilver(), thumb: .white) private var valueShouldChange = false - private var canChangeValue = false +// private var canChangeValue = false private var shouldTouchToSwitch = false - private var valueChangedBlock: ValueChangeBlock? - private var actionBlock: ValueChangeBlock? + private var valueChangedBlock: ActionBlock? + private var actionBlock: ActionBlock? // Sizes are from InVision design specs. static let trackSize = CGSize(width: 46, height: 24) @@ -90,13 +88,13 @@ public typealias ValueChangeBlock = () -> () self.init(frame: .zero) } - public convenience init(isOn: Bool, changeBlock: ValueChangeBlock?) { + public convenience init(isOn: Bool, changeBlock: ActionBlock?) { self.init(frame: .zero) self.isOn = isOn valueChangedBlock = changeBlock } - public convenience init(changeBlock: ValueChangeBlock?) { + public convenience init(changeBlock: ActionBlock?) { self.init(frame: .zero) valueChangedBlock = changeBlock } @@ -116,19 +114,19 @@ public typealias ValueChangeBlock = () -> () heightConstraint?.constant = Switch.getTrackHeight() widthConstraint?.constant = Switch.getTrackWidth() - layer.cornerRadius = Switch.getTrackHeight() / 2.0 - thumbView.layer.cornerRadius = Switch.getThumbHeight() / 2.0 - thumbHeightConstraint?.constant = Switch.getThumbHeight() thumbWidthConstraint?.constant = Switch.getThumbWidth() + + layer.cornerRadius = Switch.getTrackHeight() / 2.0 + thumbView.layer.cornerRadius = Switch.getThumbHeight() / 2.0 } public override func setupView() { super.setupView() - guard !subviews.isEmpty else { return } + guard subviews.isEmpty else { return } - canChangeValue = true +// canChangeValue = true shouldTouchToSwitch = true valueShouldChange = true @@ -263,11 +261,6 @@ public typealias ValueChangeBlock = () -> () valueShouldChange = true } - open override func touchesEnded(_ touches: Set, with event: UIEvent?) { - - sendActions(for: .touchUpInside) - } - public func touchesMoved(_ touches: Set, with event: UIEvent) { if shouldTouchToSwitch { @@ -304,14 +297,13 @@ public typealias ValueChangeBlock = () -> () if shouldTouchToSwitch { thumbReformAnimation(true) - canChangeValue = true } sendActions(for: .touchCancel) } //-------------------------------------------------- - // MARK: - Animation + // MARK: - Animations //-------------------------------------------------- public func thumbEnlargeAnimation() { @@ -443,10 +435,10 @@ extension Switch { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) self.delegateObject = delegateObject - guard let dictionary = json else { return } - FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) + guard let dictionary = json else { return } + if let color = dictionary["onTintColor"] as? String { trackTintColor?.on = UIColor.mfGet(forHex: color) } From ab0ff64677e39bdb30f5906cc847c247bc0e33fb Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 10 Dec 2019 14:38:32 -0500 Subject: [PATCH 07/59] General Working order. --- MVMCoreUI/Atoms/Views/Switch.swift | 311 ++++++++++------------------- 1 file changed, 102 insertions(+), 209 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Switch.swift index da2c13bf..332bacc5 100644 --- a/MVMCoreUI/Atoms/Views/Switch.swift +++ b/MVMCoreUI/Atoms/Views/Switch.swift @@ -10,25 +10,25 @@ import MVMCore import UIKit /** - A custom implementation of Apple's UISwitch. - - Track: The background of the switch control. - Thumb: The circular indicator that slides on the track. + A custom implementation of Apple's UISwitch. + + Track: The background of the switch control. + Thumb: The circular indicator that slides on the track. */ @objcMembers open class Switch: Control, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - + public var trackTintColor: (on: UIColor?, off: UIColor?)? = (on: .mfShamrock(), off: .black) public var thumbTintColor: (on: UIColor?, off: UIColor?)? = (on: .white, off: .white) public var disabledTintColor: (track: UIColor?, thumb: UIColor?)? = (track: .mfSilver(), thumb: .white) - private var valueShouldChange = false -// private var canChangeValue = false - private var shouldTouchToSwitch = false + public var isAnimated = true + + private var valueShouldChange = true + private var shouldTouchToSwitch = true - private var valueChangedBlock: ActionBlock? private var actionBlock: ActionBlock? // Sizes are from InVision design specs. @@ -37,7 +37,12 @@ import UIKit static let shakeIntensity: CGFloat = 2 - private var thumbView = View() + private var thumbView: View = { + let view = View() + view.backgroundColor = .white + view.layer.cornerRadius = Switch.getThumbHeight() / 2.0 + return view + }() //-------------------------------------------------- // MARK: - Computed Properties @@ -53,8 +58,49 @@ import UIKit open var isOn: Bool = false { didSet { - backgroundColor = isOn ? trackTintColor?.on : trackTintColor?.off - thumbView.backgroundColor = isOn ? thumbTintColor?.on : thumbTintColor?.off + isSelected = isOn + + if isAnimated { + UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: { + if self.isOn { + self.thumbView.backgroundColor = self.thumbTintColor?.on + self.backgroundColor = self.trackTintColor?.on + + } else { + self.thumbView.backgroundColor = self.thumbTintColor?.off + self.backgroundColor = self.trackTintColor?.off + } + + }, completion: nil) + + UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.3, options: [], animations: { + if self.isOn { + self.thumbLeadingConstraint?.isActive = true + self.thumbTrailingConstraint?.isActive = false + self.relativeThumbLeadingConstraint?.isActive = false + self.relativeThumbTrailingConstraint?.isActive = true + + } else { + self.thumbLeadingConstraint?.isActive = false + self.thumbTrailingConstraint?.isActive = true + self.relativeThumbLeadingConstraint?.isActive = true + self.relativeThumbTrailingConstraint?.isActive = false + } + + self.thumbWidthConstraint?.constant = Switch.getThumbWidth() + PaddingOne + self.layoutIfNeeded() + + }, completion: nil) + + } else { + backgroundColor = isOn ? trackTintColor?.on : trackTintColor?.off + thumbView.backgroundColor = isOn ? thumbTintColor?.on : thumbTintColor?.off + } + + FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) + accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") + setNeedsLayout() + layoutIfNeeded() } } @@ -70,6 +116,9 @@ import UIKit private var thumbLeadingConstraint: NSLayoutConstraint? private var thumbTrailingConstraint: NSLayoutConstraint? + private var relativeThumbLeadingConstraint: NSLayoutConstraint? + private var relativeThumbTrailingConstraint: NSLayoutConstraint? + private var thumbHeightConstraint: NSLayoutConstraint? private var thumbWidthConstraint: NSLayoutConstraint? private var heightConstraint: NSLayoutConstraint? @@ -88,15 +137,15 @@ import UIKit self.init(frame: .zero) } - public convenience init(isOn: Bool, changeBlock: ActionBlock?) { + public convenience init(isOn: Bool, actionBlock: ActionBlock?) { self.init(frame: .zero) self.isOn = isOn - valueChangedBlock = changeBlock + self.actionBlock = actionBlock } - public convenience init(changeBlock: ActionBlock?) { + public convenience init(actionBlock: ActionBlock?) { self.init(frame: .zero) - valueChangedBlock = changeBlock + self.actionBlock = actionBlock } public required init?(coder: NSCoder) { @@ -126,10 +175,6 @@ import UIKit guard subviews.isEmpty else { return } -// canChangeValue = true - shouldTouchToSwitch = true - valueShouldChange = true - heightConstraint = heightAnchor.constraint(equalToConstant: Switch.trackSize.height) heightConstraint?.isActive = true @@ -137,10 +182,7 @@ import UIKit widthConstraint?.isActive = true layer.cornerRadius = Switch.trackSize.height / 2.0 - - let thumbView = MVMCoreUICommonViewsUtility.commonView() - thumbView.backgroundColor = .white - thumbView.layer.cornerRadius = Switch.getThumbHeight() / 2.0 + backgroundColor = trackTintColor?.off addSubview(thumbView) @@ -149,13 +191,13 @@ import UIKit thumbView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true thumbTrailingConstraint = trailingAnchor.constraint(equalTo: thumbView.trailingAnchor, constant: 1) + relativeThumbTrailingConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: thumbView.trailingAnchor) + relativeThumbTrailingConstraint?.isActive = true + + relativeThumbLeadingConstraint = thumbView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor) thumbLeadingConstraint = thumbView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1) thumbLeadingConstraint?.isActive = true - shouldTouchToSwitch = false - setState(isOn, animated: false) - shouldTouchToSwitch = true - accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Switch_buttonlabel") } @@ -176,59 +218,23 @@ import UIKit } //-------------------------------------------------- - // MARK: - Methods + // MARK: - Actions //-------------------------------------------------- - @objc func addCustomAction() { - - actionBlock?() + open override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) { + super.sendAction(action, to: target, for: event) + toggleAndAction() } - public func setState(_ state: Bool, animated: Bool) { - - setState(state, withoutBlockAnimated: animated) - valueChangedBlock?() - FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) + open override func sendActions(for controlEvents: UIControl.Event) { + super.sendActions(for: controlEvents) + toggleAndAction() } - public func setState(_ state: Bool, withoutBlockAnimated animated: Bool) { - - isOn = state - - if !shouldTouchToSwitch { - thumbEnlargeAnimation() - thumbMoveAnitmationTo(on: isOn) - thumbShakeAnitmationTo(on: isOn) - } - - if isOn { - thumbLeadingConstraint?.priority = UILayoutPriority(1) - thumbTrailingConstraint?.priority = UILayoutPriority(999) - thumbTrailingConstraint?.constant = 1 - - } else { - thumbTrailingConstraint?.priority = UILayoutPriority(1) - thumbLeadingConstraint?.priority = UILayoutPriority(999) - thumbLeadingConstraint?.constant = 1 - } - - setBaseColorToOn(isOn, animated: animated) - thumbReformAnimation(animated) - accessibilityValue = state ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") - setNeedsLayout() - layoutIfNeeded() - } - - @discardableResult - public func changeValue() -> Bool { - + /// This will toggle the state of the Switch and execute the actionBlock if provided. + public func toggleAndAction() { isOn.toggle() - shouldTouchToSwitch = false - setState(isOn, animated: true) - shouldTouchToSwitch = true - sendActions(for: .valueChanged) - - return isOn + actionBlock?() } //-------------------------------------------------- @@ -244,61 +250,24 @@ import UIKit public func touchesBegan(_ touches: Set, with event: UIEvent) { - thumbEnlargeAnimation() + UIView.animate(withDuration: 0.1, animations: { + self.thumbWidthConstraint?.constant += PaddingOne + self.layoutIfNeeded() + }) + sendActions(for: .touchDown) } - public func touchesEnded(_ touches: Set, with event: UIEvent) { + public override func touchesEnded(_ touches: Set, with event: UIEvent?) { - if shouldTouchToSwitch && valueShouldChange { - changeValue() - } - - sendActions(for: .touchUpInside) - thumbMoveAnitmationTo(on: isOn) - thumbShakeAnitmationTo(on: isOn) - thumbReformAnimation(true) + thumbReformAnimation() valueShouldChange = true - } - - public func touchesMoved(_ touches: Set, with event: UIEvent) { - - if shouldTouchToSwitch { - if touchMoves(toLeft: touches) { - thumbMoveAnitmationTo(on: false) - thumbShakeAnitmationTo(on: false) - thumbReformAnimation(true) - } else { - thumbMoveAnitmationTo(on: true) - thumbShakeAnitmationTo(on: true) - thumbReformAnimation(true) - } - } - /* - if touchIsOutSide(touches) { - sendActions(for: .touchDragOutside) - if !shouldTouchToSwitch { - thumbReformAnimation(true) - } - } else { - sendActions(for: .touchDragInside) - } - */ - } - - func touchMoves(toLeft touches: Set?) -> Bool { - - let location = touches?.first?.location(in: self) - let x = CGFloat(location?.x ?? 0.0) - return x < frame.size.width / 2.0 + sendActions(for: .touchUpInside) } public func touchesCancelled(_ touches: Set, with event: UIEvent) { - if shouldTouchToSwitch { - thumbReformAnimation(true) - } - + thumbReformAnimation() sendActions(for: .touchCancel) } @@ -306,17 +275,9 @@ import UIKit // MARK: - Animations //-------------------------------------------------- - public func thumbEnlargeAnimation() { + public func thumbReformAnimation() { - UIView.animate(withDuration: 0.1, animations: { - self.thumbWidthConstraint?.constant += PaddingOne - self.layoutIfNeeded() - }) - } - - public func thumbReformAnimation(_ animated: Bool) { - - if animated { + if isAnimated { UIView.animate(withDuration: 0.1, animations: { self.thumbWidthConstraint?.constant = Switch.getThumbWidth() self.layoutIfNeeded() @@ -326,82 +287,6 @@ import UIKit layoutIfNeeded() } } - - public func thumbMoveAnitmationTo(on toOn: Bool) { - - UIView.animate(withDuration: 0.1, animations: { - if toOn { - self.thumbLeadingConstraint?.priority = UILayoutPriority(1) - self.thumbTrailingConstraint?.priority = UILayoutPriority(999) - self.thumbTrailingConstraint?.constant = 1 - - } else { - self.thumbLeadingConstraint?.priority = UILayoutPriority(999) - self.thumbTrailingConstraint?.priority = UILayoutPriority(1) - self.thumbLeadingConstraint?.constant = 1 - } - - self.setBaseColorToOn(toOn, animated: true) - self.thumbWidthConstraint?.constant = Switch.getThumbWidth() + PaddingOne - self.valueShouldChange = toOn != self.isOn - self.layoutIfNeeded() - }) - } - - public func setBaseColorToOn(_ toOn: Bool, animated: Bool) { - - if animated { - UIView.beginAnimations(nil, context: nil) - UIView.setAnimationDuration(0.2) - UIView.setAnimationCurve(.easeIn) - - if toOn { - thumbView.backgroundColor = thumbTintColor?.on - backgroundColor = trackTintColor?.on - - } else { - thumbView.backgroundColor = thumbTintColor?.off - backgroundColor = trackTintColor?.off - } - UIView.commitAnimations() - - } else if isOn { - thumbView.backgroundColor = thumbTintColor?.on - backgroundColor = trackTintColor?.on - - } else { - thumbView.backgroundColor = thumbTintColor?.off - backgroundColor = trackTintColor?.off - } - } - - //used after thumb moving to match the behavior of default uiswitch - public func thumbShakeAnitmationTo(on toOn: Bool) { - - UIView.animate(withDuration: 0.1, delay: 0.1, options: .curveEaseIn, animations: { - if toOn { - self.thumbTrailingConstraint?.constant = Switch.shakeIntensity - } else { - self.thumbLeadingConstraint?.constant = Switch.shakeIntensity - } - - self.layoutIfNeeded() - - }, completion: nil) - - UIView.animate(withDuration: 0.2, delay: 0.1, options: [], animations: { - if toOn { - self.thumbTrailingConstraint?.constant = 1 - } else { - self.thumbLeadingConstraint?.constant = 1 - } - - self.layoutIfNeeded() - - }) { finished in - self.valueShouldChange = true - } - } } // MARK: - Accessibility @@ -455,10 +340,18 @@ extension Switch { thumbTintColor?.off = UIColor.mfGet(forHex: color) } - setState(dictionary["state"] as? Bool ?? false, animated: false) + if let state = dictionary["state"] as? Bool { + isAnimated = false + isOn = state + isAnimated = true + } - if let _ = dictionary["actionMap"] as? [String: Any] { - addTarget(self, action: #selector(addCustomAction), for: .touchUpInside) + if let actionMap = dictionary.optionalDictionaryForKey("actionMap") { +// actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } + } + + if let isAnimated = dictionary["state"] as? Bool { + self.isAnimated = isAnimated } } From c32a0d71b0a081359fde5c7fd4fe327722e4b18b Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 10 Dec 2019 15:58:59 -0500 Subject: [PATCH 08/59] good working state. --- MVMCoreUI/Atoms/Views/Switch.swift | 111 +++++++++++++++++------------ 1 file changed, 67 insertions(+), 44 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Switch.swift index 332bacc5..ee257ce8 100644 --- a/MVMCoreUI/Atoms/Views/Switch.swift +++ b/MVMCoreUI/Atoms/Views/Switch.swift @@ -26,17 +26,12 @@ import UIKit public var isAnimated = true - private var valueShouldChange = true - private var shouldTouchToSwitch = true - private var actionBlock: ActionBlock? // Sizes are from InVision design specs. static let trackSize = CGSize(width: 46, height: 24) static let thumbSize = CGSize(width: 22, height: 22) - static let shakeIntensity: CGFloat = 2 - private var thumbView: View = { let view = View() view.backgroundColor = .white @@ -56,6 +51,12 @@ import UIKit } } + public var isLocked: Bool = false { + didSet { + isUserInteractionEnabled = !isLocked + } + } + open var isOn: Bool = false { didSet { isSelected = isOn @@ -73,21 +74,10 @@ import UIKit }, completion: nil) - UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.3, options: [], animations: { - if self.isOn { - self.thumbLeadingConstraint?.isActive = true - self.thumbTrailingConstraint?.isActive = false - self.relativeThumbLeadingConstraint?.isActive = false - self.relativeThumbTrailingConstraint?.isActive = true - - } else { - self.thumbLeadingConstraint?.isActive = false - self.thumbTrailingConstraint?.isActive = true - self.relativeThumbLeadingConstraint?.isActive = true - self.relativeThumbTrailingConstraint?.isActive = false - } + UIView.animate(withDuration: 0.33, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.2, options: [], animations: { - self.thumbWidthConstraint?.constant = Switch.getThumbWidth() + PaddingOne + self.constrainThumb() + self.thumbWidthConstraint?.constant = Switch.getThumbWidth() self.layoutIfNeeded() }, completion: nil) @@ -95,6 +85,7 @@ import UIKit } else { backgroundColor = isOn ? trackTintColor?.on : trackTintColor?.off thumbView.backgroundColor = isOn ? thumbTintColor?.on : thumbTintColor?.off + self.constrainThumb() } FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) @@ -116,14 +107,17 @@ import UIKit private var thumbLeadingConstraint: NSLayoutConstraint? private var thumbTrailingConstraint: NSLayoutConstraint? - private var relativeThumbLeadingConstraint: NSLayoutConstraint? - private var relativeThumbTrailingConstraint: NSLayoutConstraint? - private var thumbHeightConstraint: NSLayoutConstraint? private var thumbWidthConstraint: NSLayoutConstraint? private var heightConstraint: NSLayoutConstraint? private var widthConstraint: NSLayoutConstraint? + private func constrainThumb() { + + self.thumbLeadingConstraint?.isActive = isOn + self.thumbTrailingConstraint?.isActive = !isOn + } + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -186,35 +180,51 @@ import UIKit addSubview(thumbView) - thumbView.heightAnchor.constraint(equalToConstant: Switch.thumbSize.height).isActive = true - thumbView.widthAnchor.constraint(equalToConstant: Switch.thumbSize.width).isActive = true + thumbHeightConstraint = thumbView.heightAnchor.constraint(equalToConstant: Switch.thumbSize.height) + thumbHeightConstraint?.isActive = true + thumbWidthConstraint = thumbView.widthAnchor.constraint(equalToConstant: Switch.thumbSize.width) + thumbWidthConstraint?.isActive = true + thumbView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + thumbView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true + bottomAnchor.constraint(greaterThanOrEqualTo: thumbView.bottomAnchor).isActive = true thumbTrailingConstraint = trailingAnchor.constraint(equalTo: thumbView.trailingAnchor, constant: 1) - relativeThumbTrailingConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: thumbView.trailingAnchor) - relativeThumbTrailingConstraint?.isActive = true - - relativeThumbLeadingConstraint = thumbView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor) thumbLeadingConstraint = thumbView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1) thumbLeadingConstraint?.isActive = true + let longPress = UILongPressGestureRecognizer(target: self, action: #selector(stretchThumb)) + addGestureRecognizer(longPress) + accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Switch_buttonlabel") } + @objc private func stretchThumb() { + + UIView.animate(withDuration: 0.1, animations: { + self.thumbWidthConstraint?.constant = 26 + self.layoutIfNeeded() + }) + } + class func getTrackWidth() -> CGFloat { - return (MFSizeObject(standardSize: Switch.trackSize.width, standardiPadPortraitSize: CGFloat(Switch.trackSize.width * 1.5)))!.getValueBasedOnApplicationWidth() + let trackWidth = Switch.trackSize.width + return (MFSizeObject(standardSize: trackWidth, standardiPadPortraitSize: CGFloat(Switch.trackSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? trackWidth } class func getTrackHeight() -> CGFloat { - return (MFSizeObject(standardSize: Switch.trackSize.height, standardiPadPortraitSize: CGFloat(Switch.trackSize.height * 1.5) ))!.getValueBasedOnApplicationWidth() + let trackHeight = Switch.trackSize.height + return (MFSizeObject(standardSize: trackHeight, standardiPadPortraitSize: CGFloat(Switch.trackSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? trackHeight } class func getThumbWidth() -> CGFloat { - return (MFSizeObject(standardSize: Switch.thumbSize.width, standardiPadPortraitSize: CGFloat(Switch.thumbSize.width * 1.5)))!.getValueBasedOnApplicationWidth() + let thumbWidth = Switch.thumbSize.width + return (MFSizeObject(standardSize: thumbWidth, standardiPadPortraitSize: CGFloat(Switch.thumbSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? thumbWidth } class func getThumbHeight() -> CGFloat { - return (MFSizeObject(standardSize: Switch.thumbSize.height, standardiPadPortraitSize: CGFloat(Switch.thumbSize.height * 1.5)))!.getValueBasedOnApplicationWidth() + let thumbHeight = Switch.thumbSize.width + return (MFSizeObject(standardSize: thumbHeight, standardiPadPortraitSize: CGFloat(Switch.thumbSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? thumbHeight } //-------------------------------------------------- @@ -248,22 +258,35 @@ import UIKit return area.contains(point) } - public func touchesBegan(_ touches: Set, with event: UIEvent) { - - UIView.animate(withDuration: 0.1, animations: { - self.thumbWidthConstraint?.constant += PaddingOne - self.layoutIfNeeded() - }) - - sendActions(for: .touchDown) - } - public override func touchesEnded(_ touches: Set, with event: UIEvent?) { thumbReformAnimation() - valueShouldChange = true sendActions(for: .touchUpInside) } + /* + open override func touchesMoved(_ touches: Set, with event: UIEvent?) { + + if shouldTouchToSwitch { + if touchMoves(toLeft: touches) { + thumbMoveAnitmationTo(on: false) + thumbShakeAnitmationTo(on: false) + thumbReformAnimation(true) + } else { + thumbMoveAnitmationTo(on: true) + thumbShakeAnitmationTo(on: true) + thumbReformAnimation(true) + } + } + + if touchIsOutSide(touches) { + sendActions(for: .touchDragOutside) + if !shouldTouchToSwitch { + thumbReformAnimation(true) + } + } else { + sendActions(for: .touchDragInside) + } + }*/ public func touchesCancelled(_ touches: Set, with event: UIEvent) { @@ -347,7 +370,7 @@ extension Switch { } if let actionMap = dictionary.optionalDictionaryForKey("actionMap") { -// actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } + actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } if let isAnimated = dictionary["state"] as? Bool { From d1ee242ca7cadbec92edd495b4bc8e4e39c2f232 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 11 Dec 2019 10:47:52 -0500 Subject: [PATCH 09/59] should did action. --- MVMCoreUI/Atoms/Views/Switch.swift | 84 ++++++++++++++---------------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Switch.swift index ee257ce8..3fbe1055 100644 --- a/MVMCoreUI/Atoms/Views/Switch.swift +++ b/MVMCoreUI/Atoms/Views/Switch.swift @@ -9,6 +9,8 @@ import MVMCore import UIKit +public typealias ActionBlockConfirmation = () -> (Bool) + /** A custom implementation of Apple's UISwitch. @@ -26,7 +28,10 @@ import UIKit public var isAnimated = true - private var actionBlock: ActionBlock? + public var didSwitchAction: ActionBlock? + public var shouldSwitchAction: ActionBlockConfirmation? = { + return { return true } + }() // Sizes are from InVision design specs. static let trackSize = CGSize(width: 46, height: 24) @@ -131,15 +136,21 @@ import UIKit self.init(frame: .zero) } - public convenience init(isOn: Bool, actionBlock: ActionBlock?) { + public convenience init(isOn: Bool, didSwitchAction: ActionBlock?) { self.init(frame: .zero) self.isOn = isOn - self.actionBlock = actionBlock + self.didSwitchAction = didSwitchAction } - public convenience init(actionBlock: ActionBlock?) { + public convenience init(didSwitchAction: ActionBlock?) { self.init(frame: .zero) - self.actionBlock = actionBlock + self.didSwitchAction = didSwitchAction + } + + public convenience init(shouldSwitchAction: ActionBlockConfirmation?, didSwitchAction: ActionBlock?) { + self.init(frame: .zero) + self.didSwitchAction = didSwitchAction + self.shouldSwitchAction = shouldSwitchAction } public required init?(coder: NSCoder) { @@ -184,7 +195,6 @@ import UIKit thumbHeightConstraint?.isActive = true thumbWidthConstraint = thumbView.widthAnchor.constraint(equalToConstant: Switch.thumbSize.width) thumbWidthConstraint?.isActive = true - thumbView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true thumbView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: thumbView.bottomAnchor).isActive = true @@ -193,20 +203,9 @@ import UIKit thumbLeadingConstraint = thumbView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1) thumbLeadingConstraint?.isActive = true - let longPress = UILongPressGestureRecognizer(target: self, action: #selector(stretchThumb)) - addGestureRecognizer(longPress) - accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Switch_buttonlabel") } - @objc private func stretchThumb() { - - UIView.animate(withDuration: 0.1, animations: { - self.thumbWidthConstraint?.constant = 26 - self.layoutIfNeeded() - }) - } - class func getTrackWidth() -> CGFloat { let trackWidth = Switch.trackSize.width return (MFSizeObject(standardSize: trackWidth, standardiPadPortraitSize: CGFloat(Switch.trackSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? trackWidth @@ -243,8 +242,11 @@ import UIKit /// This will toggle the state of the Switch and execute the actionBlock if provided. public func toggleAndAction() { - isOn.toggle() - actionBlock?() + + if let result = shouldSwitchAction?(), result { + isOn.toggle() + didSwitchAction?() + } } //-------------------------------------------------- @@ -258,35 +260,27 @@ import UIKit return area.contains(point) } + open override func touchesBegan(_ touches: Set, with event: UIEvent?) { + + UIView.animate(withDuration: 0.1, animations: { + self.thumbWidthConstraint?.constant += PaddingOne + self.layoutIfNeeded() + }) + } + public override func touchesEnded(_ touches: Set, with event: UIEvent?) { thumbReformAnimation() + + guard let coordinates: CGPoint = touches.first?.location(in: self), + coordinates.x > -20, + coordinates.x < bounds.width + 20, + coordinates.y > -20, + coordinates.y < bounds.height + 20 + else { return } + sendActions(for: .touchUpInside) } - /* - open override func touchesMoved(_ touches: Set, with event: UIEvent?) { - - if shouldTouchToSwitch { - if touchMoves(toLeft: touches) { - thumbMoveAnitmationTo(on: false) - thumbShakeAnitmationTo(on: false) - thumbReformAnimation(true) - } else { - thumbMoveAnitmationTo(on: true) - thumbShakeAnitmationTo(on: true) - thumbReformAnimation(true) - } - } - - if touchIsOutSide(touches) { - sendActions(for: .touchDragOutside) - if !shouldTouchToSwitch { - thumbReformAnimation(true) - } - } else { - sendActions(for: .touchDragInside) - } - }*/ public func touchesCancelled(_ touches: Set, with event: UIEvent) { @@ -320,7 +314,7 @@ extension Switch { } } -// MARK: FormValidationProtocol +// MARK: - FormValidationProtocol extension Switch { public func isValidField() -> Bool { @@ -370,7 +364,7 @@ extension Switch { } if let actionMap = dictionary.optionalDictionaryForKey("actionMap") { - actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } + actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } if let isAnimated = dictionary["state"] as? Bool { From eab910011ecabb3c4b13a28954450cbfec7a7ccb Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 11 Dec 2019 15:10:26 -0500 Subject: [PATCH 10/59] General working order of the Toggle. --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +- .../Views/{Switch.swift => Toggle.swift} | 196 +++++++++--------- .../MVMCoreUIMoleculeMappingObject.m | 2 +- 3 files changed, 102 insertions(+), 104 deletions(-) rename MVMCoreUI/Atoms/Views/{Switch.swift => Toggle.swift} (55%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 33529648..880427d0 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -28,7 +28,7 @@ 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; - 0AA33B3A2398524F0067DD0F /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Switch.swift */; }; + 0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.swift */; }; 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; @@ -227,7 +227,7 @@ 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; - 0AA33B392398524F0067DD0F /* Switch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = ""; }; + 0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = ""; }; 943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = ""; }; 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; @@ -781,7 +781,7 @@ 01004F2F22721C3800991ECC /* RadioButton.swift */, 943784F3236B77BB006A1E82 /* GraphView.swift */, 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */, - 0AA33B392398524F0067DD0F /* Switch.swift */, + 0AA33B392398524F0067DD0F /* Toggle.swift */, ); path = Views; sourceTree = ""; @@ -1085,7 +1085,7 @@ D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */, D2B18B7F2360913400A9AEDC /* Control.swift in Sources */, - 0AA33B3A2398524F0067DD0F /* Switch.swift in Sources */, + 0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */, D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */, DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */, D224798C231450C8003FCCF9 /* HeadlineBodySwitch.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Toggle.swift similarity index 55% rename from MVMCoreUI/Atoms/Views/Switch.swift rename to MVMCoreUI/Atoms/Views/Toggle.swift index 3fbe1055..0ee42937 100644 --- a/MVMCoreUI/Atoms/Views/Switch.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -1,5 +1,5 @@ // -// Switch.swift +// Toggle.swift // MVMCoreUI // // Created by Kevin Christiano on 12/4/19. @@ -14,33 +14,33 @@ public typealias ActionBlockConfirmation = () -> (Bool) /** A custom implementation of Apple's UISwitch. - Track: The background of the switch control. - Thumb: The circular indicator that slides on the track. + Container: The background of the toggle control. + Knob: The circular indicator that slides on the container. */ -@objcMembers open class Switch: Control, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { +@objcMembers open class Toggle: Control, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public var trackTintColor: (on: UIColor?, off: UIColor?)? = (on: .mfShamrock(), off: .black) - public var thumbTintColor: (on: UIColor?, off: UIColor?)? = (on: .white, off: .white) - public var disabledTintColor: (track: UIColor?, thumb: UIColor?)? = (track: .mfSilver(), thumb: .white) + public var containerTintColor: (on: UIColor?, off: UIColor?)? = (on: .mfShamrock(), off: .black) + public var knobTintColor: (on: UIColor?, off: UIColor?)? = (on: .white, off: .white) + public var disabledTintColor: (container: UIColor?, knob: UIColor?)? = (container: .mfSilver(), knob: .white) public var isAnimated = true - public var didSwitchAction: ActionBlock? - public var shouldSwitchAction: ActionBlockConfirmation? = { + public var didToggleAction: ActionBlock? + public var shouldToggleAction: ActionBlockConfirmation? = { return { return true } }() // Sizes are from InVision design specs. - static let trackSize = CGSize(width: 46, height: 24) - static let thumbSize = CGSize(width: 22, height: 22) + static let containerSize = CGSize(width: 46, height: 24) + static let knobSize = CGSize(width: 22, height: 22) - private var thumbView: View = { + private var knobView: View = { let view = View() view.backgroundColor = .white - view.layer.cornerRadius = Switch.getThumbHeight() / 2.0 + view.layer.cornerRadius = Toggle.getKnobHeight() / 2.0 return view }() @@ -51,8 +51,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) open override var isEnabled: Bool { didSet { isUserInteractionEnabled = isEnabled - backgroundColor = isEnabled ? trackTintColor?.on : disabledTintColor?.track - thumbView.backgroundColor = isEnabled ? thumbTintColor?.on : disabledTintColor?.thumb + backgroundColor = isEnabled ? containerTintColor?.on : disabledTintColor?.container + knobView.backgroundColor = isEnabled ? knobTintColor?.on : disabledTintColor?.knob } } @@ -69,28 +69,25 @@ public typealias ActionBlockConfirmation = () -> (Bool) if isAnimated { UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: { if self.isOn { - self.thumbView.backgroundColor = self.thumbTintColor?.on - self.backgroundColor = self.trackTintColor?.on + self.knobView.backgroundColor = self.knobTintColor?.on + self.backgroundColor = self.containerTintColor?.on } else { - self.thumbView.backgroundColor = self.thumbTintColor?.off - self.backgroundColor = self.trackTintColor?.off + self.knobView.backgroundColor = self.knobTintColor?.off + self.backgroundColor = self.containerTintColor?.off } - }, completion: nil) UIView.animate(withDuration: 0.33, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.2, options: [], animations: { - - self.constrainThumb() - self.thumbWidthConstraint?.constant = Switch.getThumbWidth() + self.constrainKnob() + self.knobWidthConstraint?.constant = Toggle.getKnobWidth() self.layoutIfNeeded() - }, completion: nil) } else { - backgroundColor = isOn ? trackTintColor?.on : trackTintColor?.off - thumbView.backgroundColor = isOn ? thumbTintColor?.on : thumbTintColor?.off - self.constrainThumb() + backgroundColor = isOn ? containerTintColor?.on : containerTintColor?.off + knobView.backgroundColor = isOn ? knobTintColor?.on : knobTintColor?.off + self.constrainKnob() } FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) @@ -110,17 +107,17 @@ public typealias ActionBlockConfirmation = () -> (Bool) // MARK: - Constraints //-------------------------------------------------- - private var thumbLeadingConstraint: NSLayoutConstraint? - private var thumbTrailingConstraint: NSLayoutConstraint? - private var thumbHeightConstraint: NSLayoutConstraint? - private var thumbWidthConstraint: NSLayoutConstraint? + private var knobLeadingConstraint: NSLayoutConstraint? + private var knobTrailingConstraint: NSLayoutConstraint? + private var knobHeightConstraint: NSLayoutConstraint? + private var knobWidthConstraint: NSLayoutConstraint? private var heightConstraint: NSLayoutConstraint? private var widthConstraint: NSLayoutConstraint? - private func constrainThumb() { + private func constrainKnob() { - self.thumbLeadingConstraint?.isActive = isOn - self.thumbTrailingConstraint?.isActive = !isOn + self.knobLeadingConstraint?.isActive = !isOn + self.knobTrailingConstraint?.isActive = isOn } //-------------------------------------------------- @@ -136,26 +133,26 @@ public typealias ActionBlockConfirmation = () -> (Bool) self.init(frame: .zero) } - public convenience init(isOn: Bool, didSwitchAction: ActionBlock?) { + public convenience init(isOn: Bool, didToggleAction: ActionBlock?) { self.init(frame: .zero) self.isOn = isOn - self.didSwitchAction = didSwitchAction + self.didToggleAction = didToggleAction } - public convenience init(didSwitchAction: ActionBlock?) { + public convenience init(didToggleAction: ActionBlock?) { self.init(frame: .zero) - self.didSwitchAction = didSwitchAction + self.didToggleAction = didToggleAction } - public convenience init(shouldSwitchAction: ActionBlockConfirmation?, didSwitchAction: ActionBlock?) { + public convenience init(shouldToggleAction: ActionBlockConfirmation?, didToggleAction: ActionBlock?) { self.init(frame: .zero) - self.didSwitchAction = didSwitchAction - self.shouldSwitchAction = shouldSwitchAction + self.didToggleAction = didToggleAction + self.shouldToggleAction = shouldToggleAction } public required init?(coder: NSCoder) { super.init(coder: coder) - fatalError("Switch does not support xib.") + fatalError("Toggle does not support xib.") } //-------------------------------------------------- @@ -165,14 +162,14 @@ public typealias ActionBlockConfirmation = () -> (Bool) public override func updateView(_ size: CGFloat) { super.updateView(size) - heightConstraint?.constant = Switch.getTrackHeight() - widthConstraint?.constant = Switch.getTrackWidth() + heightConstraint?.constant = Toggle.getContainerHeight() + widthConstraint?.constant = Toggle.getContainerWidth() - thumbHeightConstraint?.constant = Switch.getThumbHeight() - thumbWidthConstraint?.constant = Switch.getThumbWidth() + knobHeightConstraint?.constant = Toggle.getKnobHeight() + knobWidthConstraint?.constant = Toggle.getKnobWidth() - layer.cornerRadius = Switch.getTrackHeight() / 2.0 - thumbView.layer.cornerRadius = Switch.getThumbHeight() / 2.0 + layer.cornerRadius = Toggle.getContainerHeight() / 2.0 + knobView.layer.cornerRadius = Toggle.getKnobHeight() / 2.0 } public override func setupView() { @@ -180,50 +177,50 @@ public typealias ActionBlockConfirmation = () -> (Bool) guard subviews.isEmpty else { return } - heightConstraint = heightAnchor.constraint(equalToConstant: Switch.trackSize.height) + heightConstraint = heightAnchor.constraint(equalToConstant: Toggle.containerSize.height) heightConstraint?.isActive = true - widthConstraint = widthAnchor.constraint(equalToConstant: Switch.trackSize.width) + widthConstraint = widthAnchor.constraint(equalToConstant: Toggle.containerSize.width) widthConstraint?.isActive = true - layer.cornerRadius = Switch.trackSize.height / 2.0 - backgroundColor = trackTintColor?.off + layer.cornerRadius = Toggle.containerSize.height / 2.0 + backgroundColor = containerTintColor?.off - addSubview(thumbView) + addSubview(knobView) - thumbHeightConstraint = thumbView.heightAnchor.constraint(equalToConstant: Switch.thumbSize.height) - thumbHeightConstraint?.isActive = true - thumbWidthConstraint = thumbView.widthAnchor.constraint(equalToConstant: Switch.thumbSize.width) - thumbWidthConstraint?.isActive = true - thumbView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true - thumbView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: thumbView.bottomAnchor).isActive = true + knobHeightConstraint = knobView.heightAnchor.constraint(equalToConstant: Toggle.knobSize.height) + knobHeightConstraint?.isActive = true + knobWidthConstraint = knobView.widthAnchor.constraint(equalToConstant: Toggle.knobSize.width) + knobWidthConstraint?.isActive = true + knobView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true + bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true - thumbTrailingConstraint = trailingAnchor.constraint(equalTo: thumbView.trailingAnchor, constant: 1) - thumbLeadingConstraint = thumbView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1) - thumbLeadingConstraint?.isActive = true + knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1) + knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1) + knobLeadingConstraint?.isActive = true - accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Switch_buttonlabel") + accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel") } - class func getTrackWidth() -> CGFloat { - let trackWidth = Switch.trackSize.width - return (MFSizeObject(standardSize: trackWidth, standardiPadPortraitSize: CGFloat(Switch.trackSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? trackWidth + class func getContainerWidth() -> CGFloat { + let containerWidth = Toggle.containerSize.width + return (MFSizeObject(standardSize: containerWidth, standardiPadPortraitSize: CGFloat(Toggle.containerSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? containerWidth } - class func getTrackHeight() -> CGFloat { - let trackHeight = Switch.trackSize.height - return (MFSizeObject(standardSize: trackHeight, standardiPadPortraitSize: CGFloat(Switch.trackSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? trackHeight + class func getContainerHeight() -> CGFloat { + let containerHeight = Toggle.containerSize.height + return (MFSizeObject(standardSize: containerHeight, standardiPadPortraitSize: CGFloat(Toggle.containerSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? containerHeight } - class func getThumbWidth() -> CGFloat { - let thumbWidth = Switch.thumbSize.width - return (MFSizeObject(standardSize: thumbWidth, standardiPadPortraitSize: CGFloat(Switch.thumbSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? thumbWidth + class func getKnobWidth() -> CGFloat { + let knobWidth = Toggle.knobSize.width + return (MFSizeObject(standardSize: knobWidth, standardiPadPortraitSize: CGFloat(Toggle.knobSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? knobWidth } - class func getThumbHeight() -> CGFloat { - let thumbHeight = Switch.thumbSize.width - return (MFSizeObject(standardSize: thumbHeight, standardiPadPortraitSize: CGFloat(Switch.thumbSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? thumbHeight + class func getKnobHeight() -> CGFloat { + let knobHeight = Toggle.knobSize.width + return (MFSizeObject(standardSize: knobHeight, standardiPadPortraitSize: CGFloat(Toggle.knobSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? knobHeight } //-------------------------------------------------- @@ -240,12 +237,12 @@ public typealias ActionBlockConfirmation = () -> (Bool) toggleAndAction() } - /// This will toggle the state of the Switch and execute the actionBlock if provided. + /// This will toggle the state of the Toggle and execute the actionBlock if provided. public func toggleAndAction() { - if let result = shouldSwitchAction?(), result { + if let result = shouldToggleAction?(), result { isOn.toggle() - didSwitchAction?() + didToggleAction?() } } @@ -263,16 +260,17 @@ public typealias ActionBlockConfirmation = () -> (Bool) open override func touchesBegan(_ touches: Set, with event: UIEvent?) { UIView.animate(withDuration: 0.1, animations: { - self.thumbWidthConstraint?.constant += PaddingOne + self.knobWidthConstraint?.constant += PaddingOne self.layoutIfNeeded() }) } public override func touchesEnded(_ touches: Set, with event: UIEvent?) { - thumbReformAnimation() + knobReformAnimation() - guard let coordinates: CGPoint = touches.first?.location(in: self), + // Action only occurs of the user lifts up from withing acceptable region of the toggle. + guard let coordinates = touches.first?.location(in: self), coordinates.x > -20, coordinates.x < bounds.width + 20, coordinates.y > -20, @@ -284,7 +282,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) public func touchesCancelled(_ touches: Set, with event: UIEvent) { - thumbReformAnimation() + knobReformAnimation() sendActions(for: .touchCancel) } @@ -292,22 +290,23 @@ public typealias ActionBlockConfirmation = () -> (Bool) // MARK: - Animations //-------------------------------------------------- - public func thumbReformAnimation() { + public func knobReformAnimation() { if isAnimated { UIView.animate(withDuration: 0.1, animations: { - self.thumbWidthConstraint?.constant = Switch.getThumbWidth() + self.knobWidthConstraint?.constant = Toggle.getKnobWidth() self.layoutIfNeeded() }, completion: nil) + } else { - thumbWidthConstraint?.constant = Switch.getThumbWidth() + knobWidthConstraint?.constant = Toggle.getKnobWidth() layoutIfNeeded() } } } // MARK: - Accessibility -extension Switch { +extension Toggle { public func formFieldGroupName() -> String? { return json?["groupName"] as? String @@ -315,7 +314,7 @@ extension Switch { } // MARK: - FormValidationProtocol -extension Switch { +extension Toggle { public func isValidField() -> Bool { return isOn && json?["required"] as? Bool ?? false @@ -331,7 +330,7 @@ extension Switch { } // MARK: - MVMCoreUIMoleculeViewProtocol -extension Switch { +extension Toggle { public override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) @@ -342,19 +341,19 @@ extension Switch { guard let dictionary = json else { return } if let color = dictionary["onTintColor"] as? String { - trackTintColor?.on = UIColor.mfGet(forHex: color) + containerTintColor?.on = UIColor.mfGet(forHex: color) } if let color = dictionary["offTintColor"] as? String { - trackTintColor?.off = UIColor.mfGet(forHex: color) + containerTintColor?.off = UIColor.mfGet(forHex: color) } - if let color = dictionary["onThumbTintColor"] as? String { - thumbTintColor?.on = UIColor.mfGet(forHex: color) + if let color = dictionary["onKnobTintColor"] as? String { + knobTintColor?.on = UIColor.mfGet(forHex: color) } - if let color = dictionary["offThumbTintColor"] as? String { - thumbTintColor?.off = UIColor.mfGet(forHex: color) + if let color = dictionary["offKnobTintColor"] as? String { + knobTintColor?.off = UIColor.mfGet(forHex: color) } if let state = dictionary["state"] as? Bool { @@ -364,17 +363,16 @@ extension Switch { } if let actionMap = dictionary.optionalDictionaryForKey("actionMap") { - actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } + didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } - if let isAnimated = dictionary["state"] as? Bool { + if let isAnimated = dictionary["isAnimated"] as? Bool { self.isAnimated = isAnimated } } public class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - - return Switch.getTrackHeight() + return Toggle.getContainerHeight() } public func needsToBeConstrained() -> Bool { diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 4923f21d..98df5822 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -48,7 +48,7 @@ @"radioButtonLabel": RadioButtonLabel.class, @"listItem": MoleculeTableViewCell.class, @"accordionListItem": AccordionMoleculeTableViewCell.class, - @"switch": Switch.class, + @"toggle": Toggle.class, @"leftRightLabelView": LeftRightLabelView.class, @"actionDetailWithImage": ActionDetailWithImage.class, @"image": MFLoadImageView.class, From 98997bfa8046cc86d9958e5d8923570c862a28b5 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 11 Dec 2019 15:58:18 -0500 Subject: [PATCH 11/59] Comments, logical updates, refactoring. --- MVMCoreUI/Atoms/Views/Toggle.swift | 34 +++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index 0ee42937..b49104c5 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -14,6 +14,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) /** A custom implementation of Apple's UISwitch. + By default this class begins in the off state. + Container: The background of the toggle control. Knob: The circular indicator that slides on the container. */ @@ -29,6 +31,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) public var isAnimated = true public var didToggleAction: ActionBlock? + + /// Executes logic before state change. If false, then toggle state will not change and the didToggleAction will not execute. public var shouldToggleAction: ActionBlockConfirmation? = { return { return true } }() @@ -51,8 +55,9 @@ public typealias ActionBlockConfirmation = () -> (Bool) open override var isEnabled: Bool { didSet { isUserInteractionEnabled = isEnabled - backgroundColor = isEnabled ? containerTintColor?.on : disabledTintColor?.container - knobView.backgroundColor = isEnabled ? knobTintColor?.on : disabledTintColor?.knob + changeStateNoAnimation(isEnabled) + backgroundColor = isEnabled ? containerTintColor?.off : disabledTintColor?.container + knobView.backgroundColor = isEnabled ? knobTintColor?.off : disabledTintColor?.knob } } @@ -116,8 +121,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) private func constrainKnob() { - self.knobLeadingConstraint?.isActive = !isOn - self.knobTrailingConstraint?.isActive = isOn + knobLeadingConstraint?.isActive = !isOn + knobTrailingConstraint?.isActive = isOn } //-------------------------------------------------- @@ -133,17 +138,21 @@ public typealias ActionBlockConfirmation = () -> (Bool) self.init(frame: .zero) } - public convenience init(isOn: Bool, didToggleAction: ActionBlock?) { + public convenience init(isOn: Bool) { self.init(frame: .zero) self.isOn = isOn - self.didToggleAction = didToggleAction } - public convenience init(didToggleAction: ActionBlock?) { + /// - parameter isOn: Bool to set the state of the toggle. + /// - parameter didToggleAction: A closure which is executed after the toggle changes states. + public convenience init(isOn: Bool = false, didToggleAction: ActionBlock?) { self.init(frame: .zero) + changeStateNoAnimation(isOn) self.didToggleAction = didToggleAction } + /// - parameter shouldToggleAction: Takes a closure that returns a boolean. + /// - parameter didToggleAction: A closure which is executed after the toggle changes states. public convenience init(shouldToggleAction: ActionBlockConfirmation?, didToggleAction: ActionBlock?) { self.init(frame: .zero) self.didToggleAction = didToggleAction @@ -246,6 +255,13 @@ public typealias ActionBlockConfirmation = () -> (Bool) } } + private func changeStateNoAnimation(_ state: Bool) { + + isAnimated = false + isOn = state + isAnimated = true + } + //-------------------------------------------------- // MARK: - UIResponder //-------------------------------------------------- @@ -357,9 +373,7 @@ extension Toggle { } if let state = dictionary["state"] as? Bool { - isAnimated = false - isOn = state - isAnimated = true + changeStateNoAnimation(state) } if let actionMap = dictionary.optionalDictionaryForKey("actionMap") { From 639330ad5bd56755a03c35cb232c006c02910869 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 11 Dec 2019 16:03:01 -0500 Subject: [PATCH 12/59] More comments. --- MVMCoreUI/Atoms/Views/Toggle.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index b49104c5..2d056d24 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -24,10 +24,16 @@ public typealias ActionBlockConfirmation = () -> (Bool) // MARK: - Properties //-------------------------------------------------- + /// Holds the on and off colors for the container. public var containerTintColor: (on: UIColor?, off: UIColor?)? = (on: .mfShamrock(), off: .black) + + /// Holds the on and off colors for the knob. public var knobTintColor: (on: UIColor?, off: UIColor?)? = (on: .white, off: .white) + + /// Holds the on and off colors for the disabled state.. public var disabledTintColor: (container: UIColor?, knob: UIColor?)? = (container: .mfSilver(), knob: .white) + /// Set this flag to false if you do not want to animate state changes. public var isAnimated = true public var didToggleAction: ActionBlock? @@ -61,12 +67,14 @@ public typealias ActionBlockConfirmation = () -> (Bool) } } + /// Simple means to prevent user interaction with the toggle. public var isLocked: Bool = false { didSet { isUserInteractionEnabled = !isLocked } } + /// The state on the toggle. Default value: false. open var isOn: Bool = false { didSet { isSelected = isOn From 39b752d01b556b9fd0581c7fe2dd728b0920c4f0 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 12 Dec 2019 13:37:18 -0500 Subject: [PATCH 13/59] Included reset function. accounted for isAnimated state when changing isOn without animations. --- MVMCoreUI/Atoms/Views/Toggle.swift | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index 2d056d24..aff1abb3 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -220,6 +220,18 @@ public typealias ActionBlockConfirmation = () -> (Bool) accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel") } + public override func reset() { + super.reset() + + backgroundColor = containerTintColor?.off + knobView.backgroundColor = knobTintColor?.off + isAnimated = false + isOn = false + constrainKnob() + didToggleAction = nil + shouldToggleAction = { return true } + } + class func getContainerWidth() -> CGFloat { let containerWidth = Toggle.containerSize.width return (MFSizeObject(standardSize: containerWidth, standardiPadPortraitSize: CGFloat(Toggle.containerSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? containerWidth @@ -265,9 +277,12 @@ public typealias ActionBlockConfirmation = () -> (Bool) private func changeStateNoAnimation(_ state: Bool) { + // Hold state in case User wanted isAnimated to remain off. + let isAnimatedState = isAnimated + isAnimated = false isOn = state - isAnimated = true + isAnimated = isAnimatedState } //-------------------------------------------------- From 4a49c40b19068747cbfd6e1c3918dd50753458aa Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 8 Jan 2020 10:28:37 -0500 Subject: [PATCH 14/59] Using pointInside from Control. --- MVMCoreUI/Atoms/Views/Toggle.swift | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index aff1abb3..d8b73837 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -289,13 +289,6 @@ public typealias ActionBlockConfirmation = () -> (Bool) // MARK: - UIResponder //-------------------------------------------------- - override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { - - let faultTolerance: CGFloat = 20.0 - let area = bounds.insetBy(dx: -faultTolerance, dy: -faultTolerance) - return area.contains(point) - } - open override func touchesBegan(_ touches: Set, with event: UIEvent?) { UIView.animate(withDuration: 0.1, animations: { From 14f49882b1f1c485f492ef9292b478b190a1b0cc Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 8 Jan 2020 10:44:36 -0500 Subject: [PATCH 15/59] Big Self. --- MVMCoreUI/Atoms/Views/Toggle.swift | 47 ++++++++++++++--------------- MVMCoreUI/BaseClasses/Control.swift | 1 + 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index d8b73837..1a2341c2 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -93,7 +93,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) UIView.animate(withDuration: 0.33, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.2, options: [], animations: { self.constrainKnob() - self.knobWidthConstraint?.constant = Toggle.getKnobWidth() + self.knobWidthConstraint?.constant = Self.getKnobWidth() self.layoutIfNeeded() }, completion: nil) @@ -128,7 +128,6 @@ public typealias ActionBlockConfirmation = () -> (Bool) private var widthConstraint: NSLayoutConstraint? private func constrainKnob() { - knobLeadingConstraint?.isActive = !isOn knobTrailingConstraint?.isActive = isOn } @@ -179,14 +178,14 @@ public typealias ActionBlockConfirmation = () -> (Bool) public override func updateView(_ size: CGFloat) { super.updateView(size) - heightConstraint?.constant = Toggle.getContainerHeight() - widthConstraint?.constant = Toggle.getContainerWidth() + heightConstraint?.constant = Self.getContainerHeight() + widthConstraint?.constant = Self.getContainerWidth() - knobHeightConstraint?.constant = Toggle.getKnobHeight() - knobWidthConstraint?.constant = Toggle.getKnobWidth() + knobHeightConstraint?.constant = Self.getKnobHeight() + knobWidthConstraint?.constant = Self.getKnobWidth() - layer.cornerRadius = Toggle.getContainerHeight() / 2.0 - knobView.layer.cornerRadius = Toggle.getKnobHeight() / 2.0 + layer.cornerRadius = Self.getContainerHeight() / 2.0 + knobView.layer.cornerRadius = Self.getKnobHeight() / 2.0 } public override func setupView() { @@ -194,20 +193,20 @@ public typealias ActionBlockConfirmation = () -> (Bool) guard subviews.isEmpty else { return } - heightConstraint = heightAnchor.constraint(equalToConstant: Toggle.containerSize.height) + heightConstraint = heightAnchor.constraint(equalToConstant: Self.containerSize.height) heightConstraint?.isActive = true - widthConstraint = widthAnchor.constraint(equalToConstant: Toggle.containerSize.width) + widthConstraint = widthAnchor.constraint(equalToConstant: Self.containerSize.width) widthConstraint?.isActive = true - layer.cornerRadius = Toggle.containerSize.height / 2.0 + layer.cornerRadius = Self.containerSize.height / 2.0 backgroundColor = containerTintColor?.off addSubview(knobView) - knobHeightConstraint = knobView.heightAnchor.constraint(equalToConstant: Toggle.knobSize.height) + knobHeightConstraint = knobView.heightAnchor.constraint(equalToConstant: Self.knobSize.height) knobHeightConstraint?.isActive = true - knobWidthConstraint = knobView.widthAnchor.constraint(equalToConstant: Toggle.knobSize.width) + knobWidthConstraint = knobView.widthAnchor.constraint(equalToConstant: Self.knobSize.width) knobWidthConstraint?.isActive = true knobView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true @@ -233,23 +232,23 @@ public typealias ActionBlockConfirmation = () -> (Bool) } class func getContainerWidth() -> CGFloat { - let containerWidth = Toggle.containerSize.width - return (MFSizeObject(standardSize: containerWidth, standardiPadPortraitSize: CGFloat(Toggle.containerSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? containerWidth + let containerWidth = Self.containerSize.width + return (MFSizeObject(standardSize: containerWidth, standardiPadPortraitSize: CGFloat(Self.containerSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? containerWidth } class func getContainerHeight() -> CGFloat { - let containerHeight = Toggle.containerSize.height - return (MFSizeObject(standardSize: containerHeight, standardiPadPortraitSize: CGFloat(Toggle.containerSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? containerHeight + let containerHeight = Self.containerSize.height + return (MFSizeObject(standardSize: containerHeight, standardiPadPortraitSize: CGFloat(Self.containerSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? containerHeight } class func getKnobWidth() -> CGFloat { - let knobWidth = Toggle.knobSize.width - return (MFSizeObject(standardSize: knobWidth, standardiPadPortraitSize: CGFloat(Toggle.knobSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? knobWidth + let knobWidth = Self.knobSize.width + return (MFSizeObject(standardSize: knobWidth, standardiPadPortraitSize: CGFloat(Self.knobSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? knobWidth } class func getKnobHeight() -> CGFloat { - let knobHeight = Toggle.knobSize.width - return (MFSizeObject(standardSize: knobHeight, standardiPadPortraitSize: CGFloat(Toggle.knobSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? knobHeight + let knobHeight = Self.knobSize.width + return (MFSizeObject(standardSize: knobHeight, standardiPadPortraitSize: CGFloat(Self.knobSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? knobHeight } //-------------------------------------------------- @@ -326,12 +325,12 @@ public typealias ActionBlockConfirmation = () -> (Bool) if isAnimated { UIView.animate(withDuration: 0.1, animations: { - self.knobWidthConstraint?.constant = Toggle.getKnobWidth() + self.knobWidthConstraint?.constant = Self.getKnobWidth() self.layoutIfNeeded() }, completion: nil) } else { - knobWidthConstraint?.constant = Toggle.getKnobWidth() + knobWidthConstraint?.constant = Self.getKnobWidth() layoutIfNeeded() } } @@ -402,7 +401,7 @@ extension Toggle { } public class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - return Toggle.getContainerHeight() + return Self.getContainerHeight() } public func needsToBeConstrained() -> Bool { diff --git a/MVMCoreUI/BaseClasses/Control.swift b/MVMCoreUI/BaseClasses/Control.swift index 0b03ba27..5bc80003 100644 --- a/MVMCoreUI/BaseClasses/Control.swift +++ b/MVMCoreUI/BaseClasses/Control.swift @@ -72,6 +72,7 @@ extension Control: MVMCoreViewProtocol { // MARK: - MVMCoreUIMoleculeViewProtocol extension Control: MVMCoreUIMoleculeViewProtocol { + public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { self.json = json From dfa2fa334356f3f655e9fb41e7ddb4e81dc9bd70 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 8 Jan 2020 11:03:44 -0500 Subject: [PATCH 16/59] Ensure that isEnabled only triggers when false. Preventing isEnabled from changing isON. --- MVMCoreUI/Atoms/Views/Toggle.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index 1a2341c2..22956a98 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -61,7 +61,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) open override var isEnabled: Bool { didSet { isUserInteractionEnabled = isEnabled - changeStateNoAnimation(isEnabled) + changeStateNoAnimation(isEnabled ? isOn : false) backgroundColor = isEnabled ? containerTintColor?.off : disabledTintColor?.container knobView.backgroundColor = isEnabled ? knobTintColor?.off : disabledTintColor?.knob } @@ -398,6 +398,10 @@ extension Toggle { if let isAnimated = dictionary["isAnimated"] as? Bool { self.isAnimated = isAnimated } + + if let isEnabled = dictionary["isEnabled"] as? Bool{//}, !isEnabled { + self.isEnabled = isEnabled + } } public class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { From a99dd7f0a6169184991aca0518fb3b58bd12de84 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 8 Jan 2020 14:46:40 -0500 Subject: [PATCH 17/59] removed isSelected. --- MVMCoreUI/Atoms/Views/Toggle.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index 22956a98..9d97f5a6 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -77,8 +77,6 @@ public typealias ActionBlockConfirmation = () -> (Bool) /// The state on the toggle. Default value: false. open var isOn: Bool = false { didSet { - isSelected = isOn - if isAnimated { UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: { if self.isOn { From efc163ab38d2f955fd411d3fb7929a634fc445b7 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 8 Jan 2020 15:08:31 -0500 Subject: [PATCH 18/59] no com --- MVMCoreUI/Atoms/Views/Toggle.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index 9d97f5a6..17d286ac 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -397,7 +397,7 @@ extension Toggle { self.isAnimated = isAnimated } - if let isEnabled = dictionary["isEnabled"] as? Bool{//}, !isEnabled { + if let isEnabled = dictionary["isEnabled"] as? Bool{ self.isEnabled = isEnabled } } From 30d864749aa42e4b251ac2f33dbf77d495a5db7d Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Sat, 11 Jan 2020 10:30:40 +0530 Subject: [PATCH 19/59] unordered list added numbered list added --- MVMCoreUI.xcodeproj/project.pbxproj | 36 +++- .../Models/Molecules/NumberedListModel.swift | 33 +++ .../Models/Molecules/UnOrderedListModel.swift | 34 +++ .../Molecules/LabelRightMoleculesStack.swift | 199 ++++++++++++++++++ MVMCoreUI/Molecules/NumberedList.swift | 18 ++ MVMCoreUI/Molecules/UnOrderedList.swift | 18 ++ .../MVMCoreUIMoleculeMappingObject.m | 4 +- .../OtherHandlers/MoleculeObjectMapping.swift | 2 + 8 files changed, 335 insertions(+), 9 deletions(-) create mode 100644 MVMCoreUI/Models/Molecules/NumberedListModel.swift create mode 100644 MVMCoreUI/Models/Molecules/UnOrderedListModel.swift create mode 100644 MVMCoreUI/Molecules/LabelRightMoleculesStack.swift create mode 100644 MVMCoreUI/Molecules/NumberedList.swift create mode 100644 MVMCoreUI/Molecules/UnOrderedList.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index dbee02e2..bb8d8b16 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -67,6 +67,11 @@ 94C2D9A723872DA90006CF46 /* LabelAttributeColorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */; }; 94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */; }; 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */; }; + C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */; }; + C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A68023C9830D00BFB94E /* NumberedListModel.swift */; }; + C6FA7D5223C77A4A00A3614A /* UnOrderedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D4F23C77A4700A3614A /* UnOrderedList.swift */; }; + C6FA7D5323C77A4A00A3614A /* LabelRightMoleculesStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5023C77A4800A3614A /* LabelRightMoleculesStack.swift */; }; + C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5123C77A4900A3614A /* NumberedList.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; }; @@ -307,6 +312,11 @@ 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeColorModel.swift; sourceTree = ""; }; 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeImageModel.swift; sourceTree = ""; }; 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeActionModel.swift; sourceTree = ""; }; + C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedListModel.swift; sourceTree = ""; }; + C695A68023C9830D00BFB94E /* NumberedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberedListModel.swift; sourceTree = ""; }; + C6FA7D4F23C77A4700A3614A /* UnOrderedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedList.swift; sourceTree = ""; }; + C6FA7D5023C77A4800A3614A /* LabelRightMoleculesStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelRightMoleculesStack.swift; sourceTree = ""; }; + C6FA7D5123C77A4900A3614A /* NumberedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberedList.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = ""; }; @@ -538,10 +548,20 @@ 017BEB3F23620A230024EF95 /* TextFieldModel.swift */, 017BEB4123620AD20024EF95 /* FormModelProtocol.swift */, 017BEB7A236763000024EF95 /* LineModel.swift */, + C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */, + C695A68023C9830D00BFB94E /* NumberedListModel.swift */, ); path = Molecules; sourceTree = ""; }; + 0A5D59C323AD488600EFD9E9 /* Protocols */ = { + isa = PBXGroup; + children = ( + 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */, + ); + path = Protocols; + sourceTree = ""; + }; 0AA33B322398134B0067DD0F /* Primitive Models */ = { isa = PBXGroup; children = ( @@ -580,14 +600,6 @@ name = "Recovered References"; sourceTree = ""; }; - 0A5D59C323AD488600EFD9E9 /* Protocols */ = { - isa = PBXGroup; - children = ( - 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */, - ); - path = Protocols; - sourceTree = ""; - }; D213347423842FE3008E41B3 /* Controllers */ = { isa = PBXGroup; children = ( @@ -785,6 +797,9 @@ D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */, 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */, + C6FA7D5023C77A4800A3614A /* LabelRightMoleculesStack.swift */, + C6FA7D5123C77A4900A3614A /* NumberedList.swift */, + C6FA7D4F23C77A4700A3614A /* UnOrderedList.swift */, ); path = Molecules; sourceTree = ""; @@ -1318,6 +1333,7 @@ 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */, D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */, D2B18B812360945C00A9AEDC /* View.swift in Sources */, + C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */, D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */, D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */, @@ -1343,6 +1359,7 @@ D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */, 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */, 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */, + C6FA7D5323C77A4A00A3614A /* LabelRightMoleculesStack.swift in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, @@ -1358,10 +1375,12 @@ DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, D224798A2314445E003FCCF9 /* LabelSwitch.swift in Sources */, D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, + C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */, 017BEB4223620AD20024EF95 /* FormModelProtocol.swift in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, 017BEB4A236235BA0024EF95 /* ModelMoleculeViewProtocol.swift in Sources */, + C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, 012CA99A2384A687003F810F /* MFTextField+ModelExtension.swift in Sources */, 01EB3684236097C0006832FA /* MoleculeProtocol.swift in Sources */, D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, @@ -1400,6 +1419,7 @@ D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */, D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */, + C6FA7D5223C77A4A00A3614A /* UnOrderedList.swift in Sources */, 01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */, 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */, 01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */, diff --git a/MVMCoreUI/Models/Molecules/NumberedListModel.swift b/MVMCoreUI/Models/Molecules/NumberedListModel.swift new file mode 100644 index 00000000..7686ade0 --- /dev/null +++ b/MVMCoreUI/Models/Molecules/NumberedListModel.swift @@ -0,0 +1,33 @@ +// +// NumberedListModel.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 10/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class NumberedListModel: OrderListProtocol { + public var backgroundColor: String? + public static var identifier: String = "numberedList" + public var list: [LabelModel] + + enum CodingKeys: String, CodingKey { + case list + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + self.list = try typeContainer.decodeMolecules(codingKey: .list) as! [LabelModel] + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeModels(list, forKey: .list) + } +} + +public protocol OrderListProtocol: MoleculeProtocol { + var list: [LabelModel] {get} +} diff --git a/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift b/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift new file mode 100644 index 00000000..104119c3 --- /dev/null +++ b/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift @@ -0,0 +1,34 @@ +// +// UnOrderedListModel.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 10/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class UnOrderedListModel: OrderListProtocol { + + public var backgroundColor: String? + public static var identifier: String = "unOrderedList" + public var bulletChar: String? + public var list: [LabelModel] + + enum CodingKeys: String, CodingKey { + case list + case bulletChar + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + self.bulletChar = try typeContainer.decodeIfPresent(String.self, forKey: .bulletChar) + self.list = try typeContainer.decodeMolecules(codingKey: .list) as! [LabelModel] + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(bulletChar, forKey: .bulletChar) + try container.encodeModels(list, forKey: .list) + } +} diff --git a/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift b/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift new file mode 100644 index 00000000..4cb5a89b --- /dev/null +++ b/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift @@ -0,0 +1,199 @@ +// +// ListMoleculeContainer.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 03/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class LabelRightMoleculesStack: MoleculeStackView { + + var orderedListModel: OrderListProtocol? + + public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) { + let previousModel = self.orderedListModel + //Remove previously drawn views + removeAllItemViews() + guard let orderedListModel = model as? OrderListProtocol else { + return + } + + var items: [StackItem]? + if previousModel?.list.count == orderedListModel.list.count { + items = stackItems + } + stackItems = [] + self.model = MoleculeStackModel(molecules: []) + for (index, labelModel) in orderedListModel.list.enumerated() { + let labelContainer = items?[index].view as? LeftLabelRightMoleculeContainer ?? LeftLabelRightMoleculeContainer() + labelContainer.leftText = leftTextForIndex(index) + labelContainer.setWithModel(labelModel, delegateObject, additionalData) + addView(labelContainer, lastItem: index == orderedListModel.list.count - 1) + } + self.orderedListModel = orderedListModel + restack() + } + + //MARK: - Subclass should overirde this + func leftTextForIndex(_ index: Int) -> String { + return "" + } +} + +class LeftLabelRightMoleculeContainer: View { + + var label = Label.commonLabelB2(true) + var rightContainer = MVMCoreUICommonViewsUtility.commonView() + var leftContainer = MVMCoreUICommonViewsUtility.commonView() + var rightMoleculeName: String? + var rightMolecule: View? + var leftText: String? + var leftWidthConstraint: NSLayoutConstraint? + var percentage: CGFloat = 5 + + var constraintBtwViews: NSLayoutConstraint? + var spaceBtwViews: CGFloat = 0 { + didSet { + if spaceBtwViews != oldValue { + constraintBtwViews?.constant = spaceBtwViews + setNeedsDisplay() + } + } + } + + // MARK: - Inits + public override init() { + super.init() + } + + public override init(frame: CGRect) { + super.init(frame: frame) + } + + public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.init(frame: CGRect.zero) + setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func setupView() { + super.setupView() + + guard rightContainer.superview == nil else { + return + } + + translatesAutoresizingMaskIntoConstraints = false + addSubview(rightContainer) + addSubview(leftContainer) + leftContainer.addSubview(label) + + NSLayoutConstraint.constraintPinSubview(label, pinTop: true, pinBottom: false, pinLeft: true, pinRight: false) + leftContainer.rightAnchor.constraint(greaterThanOrEqualTo: label.rightAnchor).isActive = true + leftContainer.bottomAnchor.constraint(greaterThanOrEqualTo: label.bottomAnchor).isActive = true + + let lowRightConstraint = leftContainer.rightAnchor.constraint(equalTo: label.rightAnchor) + lowRightConstraint.priority = UILayoutPriority(rawValue: 200) + lowRightConstraint.isActive = true + + let lowBottomConstraint = leftContainer.bottomAnchor.constraint(equalTo: label.bottomAnchor) + lowBottomConstraint.priority = UILayoutPriority(rawValue: 200) + lowBottomConstraint.isActive = true + + NSLayoutConstraint.constraintPinSubview(leftContainer, pinTop: true, pinBottom: false, pinLeft: true, pinRight: false) + bottomAnchor.constraint(greaterThanOrEqualTo: leftContainer.bottomAnchor).isActive = true + + NSLayoutConstraint.constraintPinSubview(rightContainer, pinTop: true, pinBottom: true, pinLeft: false, pinRight: true) + constraintBtwViews = rightContainer.leftAnchor.constraint(equalTo: leftContainer.rightAnchor, constant: spaceBtwViews) + constraintBtwViews?.priority = .required + constraintBtwViews?.isActive = true + + setContentHuggingPriority(.defaultHigh, for: .vertical) + setContentHuggingPriority(.defaultHigh, for: .horizontal) + rightContainer.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) + rightContainer.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal) + leftContainer.setContentHuggingPriority(.required, for: .horizontal) + leftContainer.setContentHuggingPriority(.required, for: .vertical) + updateLeftViewWidthConstraint(percentage) + + } + + override func updateView(_ size: CGFloat) { + super.updateView(size) + rightMolecule?.updateView(size) + label.updateView(size) + updateLeftViewWidthConstraint(percentage) + setNeedsDisplay() + } + + override func reset() { + super.reset() + rightMolecule?.reset() + } + + override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) { + let previousMoleculeName = model?.moleculeName + super.setWithModel(model, delegateObject, additionalData) + removeSubviewsInRightContainer() + guard let labelModel = model as? LabelModel else { + return + } + + label.text = leftText + rightMoleculeName = labelModel.moleculeName + //For reuse purpose check that allready added molecule is same + if let rightMolecule = self.rightMolecule, previousMoleculeName == rightMoleculeName { + rightMolecule.setWithModel(labelModel, delegateObject, additionalData) + addView(rightMolecule) + } else { + if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(labelModel, delegateObject, false) { + addView(molecule) + } + } + } + + override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + let previousMoleculeName = rightMoleculeName + removeSubviewsInRightContainer() + guard let moleculeJSON = json, let _ = moleculeJSON.optionalStringForKey(KeyMoleculeName) else { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + return + } + + label.text = leftText + rightMoleculeName = moleculeJSON.optionalStringForKey(KeyMoleculeName) + //For reuse purpose check that allready added molecule is same + if let rightMolecule = self.rightMolecule, previousMoleculeName == rightMoleculeName { + rightMolecule.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) + addView(rightMolecule) + } else { + if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: false) { + addView(molecule) + } + } + } + + func updateLeftViewWidthConstraint(_ percent: CGFloat) { + percentage = percent + leftWidthConstraint?.isActive = false + leftWidthConstraint = leftContainer.widthAnchor.constraint(equalTo: widthAnchor, multiplier: CGFloat(percent/100), constant: 0) + leftWidthConstraint?.isActive = true + } + + func removeSubviewsInRightContainer() { + rightContainer.subviews.forEach({ $0.removeFromSuperview() }) + } + + func addView(_ view: UIView) { + view.translatesAutoresizingMaskIntoConstraints = false + rightContainer.addSubview(view) + NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: true, pinRight: true) + rightMolecule = view as? View + } +} diff --git a/MVMCoreUI/Molecules/NumberedList.swift b/MVMCoreUI/Molecules/NumberedList.swift new file mode 100644 index 00000000..376dffc0 --- /dev/null +++ b/MVMCoreUI/Molecules/NumberedList.swift @@ -0,0 +1,18 @@ +// +// NumberedList.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 03/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class NumberedList: LabelRightMoleculesStack { + + //MARK:- Super class override methods + override func leftTextForIndex(_ index: Int) -> String { + return String(index+1) + "." + } + +} diff --git a/MVMCoreUI/Molecules/UnOrderedList.swift b/MVMCoreUI/Molecules/UnOrderedList.swift new file mode 100644 index 00000000..4f85a483 --- /dev/null +++ b/MVMCoreUI/Molecules/UnOrderedList.swift @@ -0,0 +1,18 @@ +// +// UnOrderedList.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 03/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class UnOrderedList: LabelRightMoleculesStack { + + //MARK:- Super class override methods + override func leftTextForIndex(_ index: Int) -> String { + return (orderedListModel as? UnOrderedListModel)?.bulletChar ?? "•" + } + +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index c656ab2f..acbf75b3 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -68,7 +68,9 @@ @"dropDownListItem": DropDownFilterTableViewCell.class, @"headlineBodyButton": HeadlineBodyButton.class, @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class, - @"stackItem": StackItem.class + @"stackItem": StackItem.class, + @"unOrderedList": UnOrderedList.class, + @"numberedList": NumberedList.class } mutableCopy]; }); return mapping; diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index ac96c44f..31e645ce 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -29,5 +29,7 @@ import Foundation ModelRegistry.register(LabelAttributeUnderlineModel.self) ModelRegistry.register(LabelAttributeStrikeThroughModel.self) ModelRegistry.register(LabelAttributeActionModel.self) + ModelRegistry.register(NumberedListModel.self) + ModelRegistry.register(UnOrderedListModel.self) } } From 396c22f2434b0c5eb94c42add833adf30b978f2c Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Sat, 11 Jan 2020 16:06:25 +0530 Subject: [PATCH 20/59] doughnut chart model added doughnut chart view added doughnut chart added --- MVMCoreUI.xcodeproj/project.pbxproj | 28 ++- .../Models/Molecules/DoughnutChartModel.swift | 85 +++++++++ MVMCoreUI/Molecules/DoughnutChart.swift | 179 ++++++++++++++++++ MVMCoreUI/Molecules/DoughnutChartView.swift | 179 ++++++++++++++++++ .../MVMCoreUIMoleculeMappingObject.m | 3 +- .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 6 files changed, 466 insertions(+), 9 deletions(-) create mode 100644 MVMCoreUI/Models/Molecules/DoughnutChartModel.swift create mode 100644 MVMCoreUI/Molecules/DoughnutChart.swift create mode 100644 MVMCoreUI/Molecules/DoughnutChartView.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index dbee02e2..8efde844 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -67,6 +67,9 @@ 94C2D9A723872DA90006CF46 /* LabelAttributeColorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */; }; 94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */; }; 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */; }; + C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69323C9909000BFB94E /* DoughnutChartModel.swift */; }; + C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69523C990BC00BFB94E /* DoughnutChart.swift */; }; + C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69723C990C200BFB94E /* DoughnutChartView.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; }; @@ -307,6 +310,9 @@ 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeColorModel.swift; sourceTree = ""; }; 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeImageModel.swift; sourceTree = ""; }; 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeActionModel.swift; sourceTree = ""; }; + C695A69323C9909000BFB94E /* DoughnutChartModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChartModel.swift; sourceTree = ""; }; + C695A69523C990BC00BFB94E /* DoughnutChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChart.swift; sourceTree = ""; }; + C695A69723C990C200BFB94E /* DoughnutChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChartView.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = ""; }; @@ -530,6 +536,7 @@ 01EB368723609801006832FA /* Molecules */ = { isa = PBXGroup; children = ( + C695A69323C9909000BFB94E /* DoughnutChartModel.swift */, 01EB368923609801006832FA /* ListItemModel.swift */, 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */, 01EB368B23609801006832FA /* MoleculeStackModel.swift */, @@ -542,6 +549,14 @@ path = Molecules; sourceTree = ""; }; + 0A5D59C323AD488600EFD9E9 /* Protocols */ = { + isa = PBXGroup; + children = ( + 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */, + ); + path = Protocols; + sourceTree = ""; + }; 0AA33B322398134B0067DD0F /* Primitive Models */ = { isa = PBXGroup; children = ( @@ -580,14 +595,6 @@ name = "Recovered References"; sourceTree = ""; }; - 0A5D59C323AD488600EFD9E9 /* Protocols */ = { - isa = PBXGroup; - children = ( - 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */, - ); - path = Protocols; - sourceTree = ""; - }; D213347423842FE3008E41B3 /* Controllers */ = { isa = PBXGroup; children = ( @@ -785,6 +792,8 @@ D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */, 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */, + C695A69523C990BC00BFB94E /* DoughnutChart.swift */, + C695A69723C990C200BFB94E /* DoughnutChartView.swift */, ); path = Molecules; sourceTree = ""; @@ -1296,6 +1305,7 @@ D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */, + C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, 017BEB4023620A230024EF95 /* TextFieldModel.swift in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, @@ -1396,6 +1406,7 @@ D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */, D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */, D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */, + C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */, D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */, D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */, @@ -1404,6 +1415,7 @@ 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */, 01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */, D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */, + C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */, D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */, 946EE1BA237B66D80036751F /* ModelHelper.swift in Sources */, 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */, diff --git a/MVMCoreUI/Models/Molecules/DoughnutChartModel.swift b/MVMCoreUI/Models/Molecules/DoughnutChartModel.swift new file mode 100644 index 00000000..f6a1efb8 --- /dev/null +++ b/MVMCoreUI/Models/Molecules/DoughnutChartModel.swift @@ -0,0 +1,85 @@ +// +// DoughnutChartModel.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 10/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class DoughnutChartModel: MoleculeProtocol { + + public var backgroundColor: String? + public static var identifier: String = "doughnutChart" + public var title: LabelModel? + public var subtitle: LabelModel? + public var sections: [ChartItemModel] + public var lineWidth: CGFloat = 30.0 + public var lineGap: CGFloat = 0.05 //For 3px gap + public var spaceRequired = true + + enum CodingKeys: String, CodingKey { + case list + case title + case subtitle + case sections + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + self.title = try typeContainer.decodeMoleculeIfPresent(codingKey: .title) as? LabelModel + self.subtitle = try typeContainer.decodeMoleculeIfPresent(codingKey: .subtitle) as? LabelModel + //self.sections = try typeContainer.decodeMolecules(codingKey: .sections) as! [ChartItemModel] + + //TODO: Hasve to check with scott + self.sections = [] + guard var container = try? typeContainer.nestedUnkeyedContainer(forKey: .sections) else { + return + } + var sections = [ChartItemModel]() + while !container.isAtEnd { + if let element = try container + .decodeIfPresent(ChartItemModel.self) { + sections.append(element) + } + } + self.sections = sections + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeModelIfPresent(title, forKey: .title) + try container.encodeModelIfPresent(subtitle, forKey: .subtitle) + try container.encodeModels(sections as [Model], forKey: .sections) + } +} + + +@objcMembers public class ChartItemModel: MoleculeProtocol { + public var backgroundColor: String? + public var label: LabelModel + public var percent: CGFloat + public var color: String + public static var identifier: String = "chartItem" + + enum CodingKeys: String, CodingKey { + case label + case percent + case color + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + self.label = try typeContainer.decodeMolecule(codingKey: .label) as! LabelModel + self.percent = try typeContainer.decode(CGFloat.self, forKey: .percent) + self.color = try typeContainer.decode(String.self, forKey: .color) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeModel(label, forKey: .label) + try container.encode(percent, forKey: .percent) + try container.encode(color, forKey: .color) + } +} diff --git a/MVMCoreUI/Molecules/DoughnutChart.swift b/MVMCoreUI/Molecules/DoughnutChart.swift new file mode 100644 index 00000000..08bdefb1 --- /dev/null +++ b/MVMCoreUI/Molecules/DoughnutChart.swift @@ -0,0 +1,179 @@ +// +// DoughnutChart.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 07/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { + + var containerView = MVMCoreUICommonViewsUtility.commonView() + var containerLayer = CALayer() + var titleLabel = Label.commonLabelH3(true) + var subTitleLabel = Label.commonLabelB2(true) + var doughnutChartModel: DoughnutChartModel? { + get { return model as? DoughnutChartModel } + } + var labelContainer = ViewConstrainingView.empty() + var heightConstraint: NSLayoutConstraint? + + private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 150)! + //private var lineSizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 30)! + + var height: CGFloat = 150 { + didSet { + if height != oldValue { + sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: height)! + updateContainer() + drawGraph() + } + } + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + titleLabel.updateView(size) + subTitleLabel.updateView(size) + updateContainer() + drawGraph() + } + + open override func reset() { + super.reset() + titleLabel.reset() + subTitleLabel.reset() + clearLayers() + } + + public func setAsMolecule() { + titleLabel.setAsMolecule() + subTitleLabel.setAsMolecule() + } + + open override func setupView() { + super.setupView() + guard containerView.superview == nil else { + return + } + addSubview(containerView) + addSubview(labelContainer) + + labelContainer.addSubview(titleLabel) + labelContainer.addSubview(subTitleLabel) + titleLabel.textAlignment = .center + subTitleLabel.textAlignment = .center + + //Make label font size to adjust width if label content is high + titleLabel.numberOfLines = 1 + titleLabel.adjustsFontSizeToFitWidth = true + + containerView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true + containerView.topAnchor.constraint(equalTo: topAnchor).isActive = true + bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true + trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + containerView.layer.addSublayer(containerLayer) + heightConstraint = containerView.heightAnchor.constraint(equalToConstant: + sizeObject.getValueBasedOnApplicationWidth()) + heightConstraint?.isActive = true + containerView.widthAnchor.constraint(equalTo: containerView.heightAnchor).isActive = true + + labelContainer.leftPin = labelContainer.leftAnchor.constraint(greaterThanOrEqualTo: containerView.leftAnchor, constant: lineWidth()) + labelContainer.leftPin?.isActive = true + labelContainer.topPin = labelContainer.topAnchor.constraint(greaterThanOrEqualTo: containerView.topAnchor, constant: lineWidth()) + labelContainer.topPin?.isActive = true + labelContainer.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true + labelContainer.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true + + NSLayoutConstraint.constraintPinSubview(titleLabel, pinTop: true, pinBottom: false, pinLeft: true, pinRight: true) + NSLayoutConstraint.constraintPinSubview(subTitleLabel, pinTop: false, pinBottom: true, pinLeft: true, pinRight: true) + _ = NSLayoutConstraint(pinFirstView: titleLabel, toSecondView: subTitleLabel, withConstant: 0, directionVertical: true) + //Rotate view for initial draw + containerLayer.transform = CATransform3DMakeRotation(1 * .pi, 0.0, 0.0, 1.0) + + } + + open override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) { + super.setWithModel(model, delegateObject, additionalData) + clearLayers() + guard let doughnutChartModel = model as? DoughnutChartModel else { + return + } + titleLabel.setWithModel(doughnutChartModel.title, delegateObject, additionalData) + subTitleLabel.setWithModel(doughnutChartModel.subtitle, delegateObject, additionalData) + titleLabel.textAlignment = .center + subTitleLabel.textAlignment = .center + //lineSizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: doughnutChartModel.lineWidth)! + updateLabelContainer() + drawGraph() + } + + func drawGraph() { + clearLayers() + let widthHeight = sizeObject.getValueBasedOnApplicationWidth() + containerLayer.frame = CGRect(x: 0, y: 0, + width: widthHeight, + height: widthHeight) + if let doughnutChart = doughnutChartModel { + var prevPercent: CGFloat = 0.0 + //If Single item in array. We don't need gap + doughnutChartModel?.lineGap = (doughnutChart.sections.count == 1) ? 0.0 : doughnutChart.lineGap + for model in doughnutChart.sections { + prevPercent += drawBar(model, prevPercent, doughnutChart.spaceRequired, doughnutChart.lineGap) + } + } + } + + func drawBar(_ chartModel: ChartItemModel, _ prevPercent: CGFloat, _ spaceRequired: Bool, _ lineGap: CGFloat) -> CGFloat { + + let shapeLayer = CAShapeLayer() + shapeLayer.frame = containerLayer.frame + shapeLayer.lineWidth = lineWidth() + //lineSizeObject.getValueBasedOnApplicationWidth() + shapeLayer.fillColor = nil + shapeLayer.strokeColor = UIColor.mfGet(forHex: chartModel.color).cgColor + + let arcCenter = shapeLayer.position + let radius = shapeLayer.bounds.size.width / 2.0 - lineWidth()/2.0 + //lineSizeObject.getValueBasedOnApplicationWidth() / 2.0 + let clockwise = true + + let value: CGFloat = chartModel.percent + let gap: CGFloat = spaceRequired ? lineGap : 0.0 + let startAngle = ((prevPercent / 100.0) * 2 * .pi) - (0.5 * .pi) + let endAngle = ((value / 100.0) * 2 * .pi) + startAngle - gap + let circlePath = UIBezierPath(arcCenter: arcCenter, + radius: radius, + startAngle: startAngle, + endAngle: endAngle, + clockwise: clockwise) + + shapeLayer.path = circlePath.cgPath + containerLayer.addSublayer(shapeLayer) + return value + } + + func clearLayers() { + containerLayer.sublayers?.forEach({ $0.removeFromSuperlayer() }) + } + + func updateContainer() { + heightConstraint?.constant = sizeObject.getValueBasedOnApplicationWidth() + updateLabelContainer() + setNeedsDisplay() + } + + func lineWidth() -> CGFloat { + return doughnutChartModel?.lineWidth ?? 30 + //lineSizeObject.getValueBasedOnApplicationWidth() + 5 + } + + func updateLabelContainer() { + labelContainer.leftPin?.constant = lineWidth() + labelContainer.topPin?.constant = lineWidth() + labelContainer.setNeedsDisplay() + } + +} diff --git a/MVMCoreUI/Molecules/DoughnutChartView.swift b/MVMCoreUI/Molecules/DoughnutChartView.swift new file mode 100644 index 00000000..ebe77200 --- /dev/null +++ b/MVMCoreUI/Molecules/DoughnutChartView.swift @@ -0,0 +1,179 @@ +// +// DoughnutChartView.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 26/12/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class DoughnutChartView: View { + + var doughnutChart = DoughnutChart(frame: CGRect.zero) + var colorLablesStack = ColorViewLabelsStack() + var container = MVMCoreUICommonViewsUtility.commonView() + var doughnutChartModel: DoughnutChartModel? { + get { return model as? DoughnutChartModel } + } + + open override func setupView() { + super.setupView() + guard container.superview == nil else { + return + } + + addSubview(container) + doughnutChart.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(doughnutChart) + colorLablesStack.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(colorLablesStack) + + NSLayoutConstraint.constraintPinSubview(container, pinTop: true, pinBottom: true, pinLeft: true, pinRight: true) + doughnutChart.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true + doughnutChart.topAnchor.constraint(equalTo: container.topAnchor, constant: PaddingFour).isActive = true + container.bottomAnchor.constraint(greaterThanOrEqualTo: doughnutChart.bottomAnchor).isActive = true + + let containerBottomAnchor = container.bottomAnchor.constraint(equalTo: doughnutChart.bottomAnchor) + containerBottomAnchor.priority = UILayoutPriority(rawValue: 200) + containerBottomAnchor.isActive = true + + let colorLablesBottomAnchor = container.bottomAnchor.constraint(equalTo: colorLablesStack.bottomAnchor) + colorLablesBottomAnchor.priority = UILayoutPriority(rawValue: 204) + colorLablesBottomAnchor.isActive = true + + let colorLablesTopAnchor = colorLablesStack.topAnchor.constraint(equalTo: doughnutChart.topAnchor) + colorLablesTopAnchor.priority = UILayoutPriority(rawValue: 204) + colorLablesTopAnchor.isActive = true + + colorLablesStack.topAnchor.constraint(greaterThanOrEqualTo: doughnutChart.topAnchor).isActive = true + container.bottomAnchor.constraint(greaterThanOrEqualTo: colorLablesStack.bottomAnchor).isActive = true + container.trailingAnchor.constraint(greaterThanOrEqualTo: colorLablesStack.trailingAnchor).isActive = true + + let centerY = colorLablesStack.centerYAnchor.constraint(equalTo: doughnutChart.centerYAnchor) + centerY.priority = .defaultLow + centerY.isActive = true + + colorLablesStack.leadingAnchor.constraint(equalTo: doughnutChart.trailingAnchor, constant: PaddingThree).isActive = true + colorLablesStack.backgroundColor = UIColor.clear + + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + doughnutChart.updateView(size) + colorLablesStack.updateView(size) + } + + open override func reset() { + super.reset() + colorLablesStack.reset() + } + + open override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) { + super.setWithModel(model, delegateObject, additionalData) + doughnutChart.clearLayers() + colorLablesStack.removeAllItemViews() + doughnutChart.setWithModel(model, delegateObject, additionalData) + colorLablesStack.setWithModel(model, delegateObject, additionalData) + } + + open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + if model == nil { + let data = try! JSONSerialization.data(withJSONObject: json!) + let decoder = JSONDecoder() + let model = try! decoder.decode(DoughnutChartModel.self, from: data) + setWithModel(model, delegateObject, additionalData as? [String : AnyHashable]) + } else { + setWithModel(model, delegateObject, additionalData as? [String : AnyHashable]) + } + } + +} + +class ColorViewLabelsStack: MoleculeStackView { + + var dougnutChartModel: DoughnutChartModel? + + override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) { + let previousModel = self.dougnutChartModel + removeAllItemViews() + guard let dougnutChartModel = model as? DoughnutChartModel else { + return + } + var items: [StackItem]? + if previousModel?.sections.count == dougnutChartModel.sections.count { + items = stackItems + } + stackItems = [] + self.model = MoleculeStackModel(molecules: []) + for (index, chartItemModel) in dougnutChartModel.sections.enumerated() { + let colorViewWithLabel = items?[index].view as? ColorViewWithLabel ?? ColorViewWithLabel() + colorViewWithLabel.setWithModel(chartItemModel, delegateObject, additionalData) + addView(colorViewWithLabel, lastItem: index == dougnutChartModel.sections.count - 1) + } + self.dougnutChartModel = dougnutChartModel + restack() + } +} + +class ColorViewWithLabel: View, MVMCoreUIViewConstrainingProtocol { + + var label = Label.commonLabelB2(true) + var colorView = MVMCoreUICommonViewsUtility.commonView() + private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 8)! + var heightConstraint: NSLayoutConstraint? + + override func setupView() { + super.setupView() + guard colorView.superview == nil else { + return + } + translatesAutoresizingMaskIntoConstraints = false + addSubview(colorView) + addSubview(label) + + heightConstraint = colorView.heightAnchor.constraint(equalToConstant: sizeObject.getValueBasedOnApplicationWidth()) + heightConstraint?.isActive = true + colorView.widthAnchor.constraint(equalTo: colorView.heightAnchor).isActive = true + colorView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true + colorView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + + label.leadingAnchor.constraint(equalTo: colorView.trailingAnchor, constant: PaddingOne).isActive = true + label.topAnchor.constraint(equalTo: topAnchor).isActive = true + trailingAnchor.constraint(greaterThanOrEqualTo: label.trailingAnchor).isActive = true + bottomAnchor.constraint(equalTo: label.bottomAnchor).isActive = true + + } + + override func updateView(_ size: CGFloat) { + super.updateView(size) + label.updateView(size) + heightConstraint?.constant = sizeObject.getValueBased(onSize: size) + setNeedsDisplay() + } + + override func reset() { + super.reset() + label.reset() + } + + func setAsMolecule() { + label.setAsMolecule() + } + + override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let chartItemModel = model as? ChartItemModel else { + return + } + label.setWithModel(chartItemModel.label, delegateObject, additionalData) + colorView.backgroundColor = UIColor.mfGet(forHex: chartItemModel.color) + } + + override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + Label.setUILabel(label, withJSON: json?.optionalDictionaryForKey("label"), delegate: delegateObject, additionalData: additionalData) + colorView.backgroundColor = UIColor.mfGet(forHex: json?.optionalStringForKey("color") ?? "#000000") + } + +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index c656ab2f..4b597288 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -68,7 +68,8 @@ @"dropDownListItem": DropDownFilterTableViewCell.class, @"headlineBodyButton": HeadlineBodyButton.class, @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class, - @"stackItem": StackItem.class + @"stackItem": StackItem.class, + @"doughnutChart": DoughnutChartView.class } mutableCopy]; }); return mapping; diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index ac96c44f..651d18a7 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -29,5 +29,6 @@ import Foundation ModelRegistry.register(LabelAttributeUnderlineModel.self) ModelRegistry.register(LabelAttributeStrikeThroughModel.self) ModelRegistry.register(LabelAttributeActionModel.self) + ModelRegistry.register(DoughnutChartModel.self) } } From b4859988c20a42df28de56757cc508c0063993c9 Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Mon, 13 Jan 2020 19:52:04 +0530 Subject: [PATCH 21/59] set with json removed --- .../Molecules/LabelRightMoleculesStack.swift | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift b/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift index 4cb5a89b..58a5ba7b 100644 --- a/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift +++ b/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift @@ -72,11 +72,6 @@ class LeftLabelRightMoleculeContainer: View { super.init(frame: frame) } - public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - super.init(frame: CGRect.zero) - setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - } - public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -157,28 +152,6 @@ class LeftLabelRightMoleculeContainer: View { } } - override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - let previousMoleculeName = rightMoleculeName - removeSubviewsInRightContainer() - guard let moleculeJSON = json, let _ = moleculeJSON.optionalStringForKey(KeyMoleculeName) else { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - return - } - - label.text = leftText - rightMoleculeName = moleculeJSON.optionalStringForKey(KeyMoleculeName) - //For reuse purpose check that allready added molecule is same - if let rightMolecule = self.rightMolecule, previousMoleculeName == rightMoleculeName { - rightMolecule.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) - addView(rightMolecule) - } else { - if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: false) { - addView(molecule) - } - } - } - func updateLeftViewWidthConstraint(_ percent: CGFloat) { percentage = percent leftWidthConstraint?.isActive = false From be094b3cf91879c7d654d3b25c97ce585e3cb2e0 Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Mon, 13 Jan 2020 22:49:51 +0530 Subject: [PATCH 22/59] review comments updated --- .../Models/Molecules/DoughnutChartModel.swift | 61 +------------------ MVMCoreUI/Molecules/DoughnutChart.swift | 21 ++++--- MVMCoreUI/Molecules/DoughnutChartView.swift | 5 -- 3 files changed, 14 insertions(+), 73 deletions(-) diff --git a/MVMCoreUI/Models/Molecules/DoughnutChartModel.swift b/MVMCoreUI/Models/Molecules/DoughnutChartModel.swift index f6a1efb8..15ecab85 100644 --- a/MVMCoreUI/Models/Molecules/DoughnutChartModel.swift +++ b/MVMCoreUI/Models/Molecules/DoughnutChartModel.swift @@ -9,50 +9,13 @@ import Foundation @objcMembers public class DoughnutChartModel: MoleculeProtocol { - public var backgroundColor: String? public static var identifier: String = "doughnutChart" public var title: LabelModel? public var subtitle: LabelModel? public var sections: [ChartItemModel] - public var lineWidth: CGFloat = 30.0 - public var lineGap: CGFloat = 0.05 //For 3px gap - public var spaceRequired = true - - enum CodingKeys: String, CodingKey { - case list - case title - case subtitle - case sections - } - - required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - self.title = try typeContainer.decodeMoleculeIfPresent(codingKey: .title) as? LabelModel - self.subtitle = try typeContainer.decodeMoleculeIfPresent(codingKey: .subtitle) as? LabelModel - //self.sections = try typeContainer.decodeMolecules(codingKey: .sections) as! [ChartItemModel] - - //TODO: Hasve to check with scott - self.sections = [] - guard var container = try? typeContainer.nestedUnkeyedContainer(forKey: .sections) else { - return - } - var sections = [ChartItemModel]() - while !container.isAtEnd { - if let element = try container - .decodeIfPresent(ChartItemModel.self) { - sections.append(element) - } - } - self.sections = sections - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeModelIfPresent(title, forKey: .title) - try container.encodeModelIfPresent(subtitle, forKey: .subtitle) - try container.encodeModels(sections as [Model], forKey: .sections) - } + public var lineWidth: CGFloat? + public var spaceRequired: Bool? } @@ -62,24 +25,4 @@ import Foundation public var percent: CGFloat public var color: String public static var identifier: String = "chartItem" - - enum CodingKeys: String, CodingKey { - case label - case percent - case color - } - - required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - self.label = try typeContainer.decodeMolecule(codingKey: .label) as! LabelModel - self.percent = try typeContainer.decode(CGFloat.self, forKey: .percent) - self.color = try typeContainer.decode(String.self, forKey: .color) - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeModel(label, forKey: .label) - try container.encode(percent, forKey: .percent) - try container.encode(color, forKey: .color) - } } diff --git a/MVMCoreUI/Molecules/DoughnutChart.swift b/MVMCoreUI/Molecules/DoughnutChart.swift index 08bdefb1..ac19af7d 100644 --- a/MVMCoreUI/Molecules/DoughnutChart.swift +++ b/MVMCoreUI/Molecules/DoughnutChart.swift @@ -21,7 +21,6 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { var heightConstraint: NSLayoutConstraint? private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 150)! - //private var lineSizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 30)! var height: CGFloat = 150 { didSet { @@ -105,7 +104,6 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { subTitleLabel.setWithModel(doughnutChartModel.subtitle, delegateObject, additionalData) titleLabel.textAlignment = .center subTitleLabel.textAlignment = .center - //lineSizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: doughnutChartModel.lineWidth)! updateLabelContainer() drawGraph() } @@ -118,20 +116,17 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { height: widthHeight) if let doughnutChart = doughnutChartModel { var prevPercent: CGFloat = 0.0 - //If Single item in array. We don't need gap - doughnutChartModel?.lineGap = (doughnutChart.sections.count == 1) ? 0.0 : doughnutChart.lineGap for model in doughnutChart.sections { - prevPercent += drawBar(model, prevPercent, doughnutChart.spaceRequired, doughnutChart.lineGap) + prevPercent += drawBar(model, prevPercent) } } } - func drawBar(_ chartModel: ChartItemModel, _ prevPercent: CGFloat, _ spaceRequired: Bool, _ lineGap: CGFloat) -> CGFloat { + func drawBar(_ chartModel: ChartItemModel, _ prevPercent: CGFloat) -> CGFloat { let shapeLayer = CAShapeLayer() shapeLayer.frame = containerLayer.frame shapeLayer.lineWidth = lineWidth() - //lineSizeObject.getValueBasedOnApplicationWidth() shapeLayer.fillColor = nil shapeLayer.strokeColor = UIColor.mfGet(forHex: chartModel.color).cgColor @@ -141,7 +136,7 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { let clockwise = true let value: CGFloat = chartModel.percent - let gap: CGFloat = spaceRequired ? lineGap : 0.0 + let gap: CGFloat = spaceReuired() ? lineGap() : 0.0 let startAngle = ((prevPercent / 100.0) * 2 * .pi) - (0.5 * .pi) let endAngle = ((value / 100.0) * 2 * .pi) + startAngle - gap let circlePath = UIBezierPath(arcCenter: arcCenter, @@ -167,7 +162,15 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { func lineWidth() -> CGFloat { return doughnutChartModel?.lineWidth ?? 30 - //lineSizeObject.getValueBasedOnApplicationWidth() + 5 + } + + func lineGap() -> CGFloat { + //If array is having the single item then no space required + return doughnutChartModel?.sections.count == 1 ? 0.0 : 0.05 + } + + func spaceReuired() -> Bool { + return doughnutChartModel?.spaceRequired ?? true } func updateLabelContainer() { diff --git a/MVMCoreUI/Molecules/DoughnutChartView.swift b/MVMCoreUI/Molecules/DoughnutChartView.swift index ebe77200..95e23440 100644 --- a/MVMCoreUI/Molecules/DoughnutChartView.swift +++ b/MVMCoreUI/Molecules/DoughnutChartView.swift @@ -171,9 +171,4 @@ class ColorViewWithLabel: View, MVMCoreUIViewConstrainingProtocol { colorView.backgroundColor = UIColor.mfGet(forHex: chartItemModel.color) } - override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - Label.setUILabel(label, withJSON: json?.optionalDictionaryForKey("label"), delegate: delegateObject, additionalData: additionalData) - colorView.backgroundColor = UIColor.mfGet(forHex: json?.optionalStringForKey("color") ?? "#000000") - } - } From e6079eab55ae91f602d1c5c08acb8798c6a9b2e4 Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Tue, 14 Jan 2020 00:11:41 +0530 Subject: [PATCH 23/59] updated model --- .../Models/Molecules/NumberedListModel.swift | 14 -------------- .../Models/Molecules/UnOrderedListModel.swift | 18 ------------------ 2 files changed, 32 deletions(-) diff --git a/MVMCoreUI/Models/Molecules/NumberedListModel.swift b/MVMCoreUI/Models/Molecules/NumberedListModel.swift index 7686ade0..2a440b27 100644 --- a/MVMCoreUI/Models/Molecules/NumberedListModel.swift +++ b/MVMCoreUI/Models/Molecules/NumberedListModel.swift @@ -12,20 +12,6 @@ import Foundation public var backgroundColor: String? public static var identifier: String = "numberedList" public var list: [LabelModel] - - enum CodingKeys: String, CodingKey { - case list - } - - required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - self.list = try typeContainer.decodeMolecules(codingKey: .list) as! [LabelModel] - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeModels(list, forKey: .list) - } } public protocol OrderListProtocol: MoleculeProtocol { diff --git a/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift b/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift index 104119c3..a795e903 100644 --- a/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift +++ b/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift @@ -9,26 +9,8 @@ import Foundation @objcMembers public class UnOrderedListModel: OrderListProtocol { - public var backgroundColor: String? public static var identifier: String = "unOrderedList" public var bulletChar: String? public var list: [LabelModel] - - enum CodingKeys: String, CodingKey { - case list - case bulletChar - } - - required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - self.bulletChar = try typeContainer.decodeIfPresent(String.self, forKey: .bulletChar) - self.list = try typeContainer.decodeMolecules(codingKey: .list) as! [LabelModel] - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(bulletChar, forKey: .bulletChar) - try container.encodeModels(list, forKey: .list) - } } From a6dc16889c81c1f9b929a36be0ba50bc4d3c1fb2 Mon Sep 17 00:00:00 2001 From: panxi Date: Mon, 13 Jan 2020 17:07:16 -0500 Subject: [PATCH 24/59] fix error from merging --- MVMCoreUI/Models/Molecules/NumberedListModel.swift | 2 +- MVMCoreUI/Models/Molecules/UnOrderedListModel.swift | 2 +- MVMCoreUI/Molecules/LabelRightMoleculesStack.swift | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Models/Molecules/NumberedListModel.swift b/MVMCoreUI/Models/Molecules/NumberedListModel.swift index 2a440b27..496db1b1 100644 --- a/MVMCoreUI/Models/Molecules/NumberedListModel.swift +++ b/MVMCoreUI/Models/Molecules/NumberedListModel.swift @@ -9,7 +9,7 @@ import Foundation @objcMembers public class NumberedListModel: OrderListProtocol { - public var backgroundColor: String? + public var backgroundColor: Color? public static var identifier: String = "numberedList" public var list: [LabelModel] } diff --git a/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift b/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift index a795e903..2c80dc6f 100644 --- a/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift +++ b/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift @@ -9,7 +9,7 @@ import Foundation @objcMembers public class UnOrderedListModel: OrderListProtocol { - public var backgroundColor: String? + public var backgroundColor: Color? public static var identifier: String = "unOrderedList" public var bulletChar: String? public var list: [LabelModel] diff --git a/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift b/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift index 58a5ba7b..312927fd 100644 --- a/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift +++ b/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift @@ -12,7 +12,7 @@ open class LabelRightMoleculesStack: MoleculeStackView { var orderedListModel: OrderListProtocol? - public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) { + public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { let previousModel = self.orderedListModel //Remove previously drawn views removeAllItemViews() @@ -64,8 +64,8 @@ class LeftLabelRightMoleculeContainer: View { } // MARK: - Inits - public override init() { - super.init() + public convenience init() { + self.init(frame:.zero) } public override init(frame: CGRect) { @@ -131,7 +131,7 @@ class LeftLabelRightMoleculeContainer: View { rightMolecule?.reset() } - override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [String : AnyHashable]?) { + public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { let previousMoleculeName = model?.moleculeName super.setWithModel(model, delegateObject, additionalData) removeSubviewsInRightContainer() From cd3555466f7b21d3b487429869e96e4a57726ed6 Mon Sep 17 00:00:00 2001 From: panxi Date: Mon, 13 Jan 2020 17:18:49 -0500 Subject: [PATCH 25/59] remove duplicate --- MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index ff0a6056..0aee8405 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -73,7 +73,6 @@ @"headlineBodyButton": HeadlineBodyButton.class, @"stackItem": StackItem.class, @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class, - @"stackItem": StackItem.class, @"unOrderedList": UnOrderedList.class, @"numberedList": NumberedList.class, @"headLineBodyCaretLinkImage" : HeadLineBodyCaretLinkImage.class From 7e38657b63aee00d4b326c0855b53d7e57796f9a Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Tue, 14 Jan 2020 20:48:15 +0530 Subject: [PATCH 26/59] review comments updated models updated --- .../Models/Molecules/NumberedListModel.swift | 18 ++++++++++++++++-- .../Models/Molecules/UnOrderedListModel.swift | 19 ++++++++++++++++++- .../Molecules/LabelRightMoleculesStack.swift | 17 ++++++----------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/MVMCoreUI/Models/Molecules/NumberedListModel.swift b/MVMCoreUI/Models/Molecules/NumberedListModel.swift index 496db1b1..380c193f 100644 --- a/MVMCoreUI/Models/Molecules/NumberedListModel.swift +++ b/MVMCoreUI/Models/Molecules/NumberedListModel.swift @@ -11,9 +11,23 @@ import Foundation @objcMembers public class NumberedListModel: OrderListProtocol { public var backgroundColor: Color? public static var identifier: String = "numberedList" - public var list: [LabelModel] + public var list: [MoleculeProtocol] + + enum CodingKeys: String, CodingKey { + case list + } + + public required init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + list = try typeContainer.decodeMolecules(codingKey: .list) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeModels(list, forKey: .list) + } } public protocol OrderListProtocol: MoleculeProtocol { - var list: [LabelModel] {get} + var list: [MoleculeProtocol] {get} } diff --git a/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift b/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift index 2c80dc6f..8d3280d9 100644 --- a/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift +++ b/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift @@ -12,5 +12,22 @@ import Foundation public var backgroundColor: Color? public static var identifier: String = "unOrderedList" public var bulletChar: String? - public var list: [LabelModel] + public var list: [MoleculeProtocol] + + enum CodingKeys: String, CodingKey { + case bulletChar + case list + } + + public required init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + bulletChar = try typeContainer.decodeIfPresent(String.self, forKey: .bulletChar) + list = try typeContainer.decodeMolecules(codingKey: .list) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(bulletChar, forKey: .bulletChar) + try container.encodeModels(list, forKey: .list) + } } diff --git a/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift b/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift index 312927fd..693df09c 100644 --- a/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift +++ b/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift @@ -110,10 +110,6 @@ class LeftLabelRightMoleculeContainer: View { setContentHuggingPriority(.defaultHigh, for: .vertical) setContentHuggingPriority(.defaultHigh, for: .horizontal) - rightContainer.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) - rightContainer.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal) - leftContainer.setContentHuggingPriority(.required, for: .horizontal) - leftContainer.setContentHuggingPriority(.required, for: .vertical) updateLeftViewWidthConstraint(percentage) } @@ -132,21 +128,20 @@ class LeftLabelRightMoleculeContainer: View { } public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - let previousMoleculeName = model?.moleculeName + let previousMoleculeName = self.rightMoleculeName super.setWithModel(model, delegateObject, additionalData) removeSubviewsInRightContainer() - guard let labelModel = model as? LabelModel else { + label.text = leftText + rightMoleculeName = model?.moleculeName + guard let validModel = model else { return } - - label.text = leftText - rightMoleculeName = labelModel.moleculeName //For reuse purpose check that allready added molecule is same if let rightMolecule = self.rightMolecule, previousMoleculeName == rightMoleculeName { - rightMolecule.setWithModel(labelModel, delegateObject, additionalData) + rightMolecule.setWithModel(validModel, delegateObject, additionalData) addView(rightMolecule) } else { - if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(labelModel, delegateObject, false) { + if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(validModel, delegateObject, false) { addView(molecule) } } From 703e0cd32bc06b1866fee7a95c5dbb411b3a699c Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 15 Jan 2020 12:38:31 -0500 Subject: [PATCH 27/59] Convenience to access cgColor. --- MVMCoreUI/Models/Primitive Models/Color.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MVMCoreUI/Models/Primitive Models/Color.swift b/MVMCoreUI/Models/Primitive Models/Color.swift index e4c0e4fa..d72e1af9 100644 --- a/MVMCoreUI/Models/Primitive Models/Color.swift +++ b/MVMCoreUI/Models/Primitive Models/Color.swift @@ -19,6 +19,11 @@ public final class Color: Codable { //-------------------------------------------------- public let uiColor: UIColor + + public var cgColor: CGColor { + return uiColor.cgColor + } + public private(set) var hex: String = "" public private(set) var name: String = "" From 388d88b47c4049cd78f2c532891e6b5ec028deeb Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 15 Jan 2020 13:13:15 -0500 Subject: [PATCH 28/59] autorResiszing exception. --- MVMCoreUI/Molecules/Items/TableViewCell.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Molecules/Items/TableViewCell.swift b/MVMCoreUI/Molecules/Items/TableViewCell.swift index 537af049..dc62ae65 100644 --- a/MVMCoreUI/Molecules/Items/TableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/TableViewCell.swift @@ -192,6 +192,7 @@ import UIKit @objc public func addCaretViewAccessory() { guard accessoryView == nil else { return } caretView = CaretView(lineWidth: 1) + caretView?.translatesAutoresizingMaskIntoConstraints = true caretView?.size = .small(.vertical) caretView?.setConstraints() From 9329f0ca15cfd8dac6a1c5979f7b8e36fbf348b2 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 15 Jan 2020 13:28:40 -0500 Subject: [PATCH 29/59] update left and right padding --- MVMCoreUI/Molecules/DoughnutChart.swift | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Molecules/DoughnutChart.swift b/MVMCoreUI/Molecules/DoughnutChart.swift index d7f25ac6..d58dc7c4 100644 --- a/MVMCoreUI/Molecules/DoughnutChart.swift +++ b/MVMCoreUI/Molecules/DoughnutChart.swift @@ -173,10 +173,15 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { return doughnutChartModel?.spaceRequired ?? true } - func updateLabelContainer() { - labelContainer.leftPin?.constant = lineWidth() - labelContainer.topPin?.constant = lineWidth() - labelContainer.setNeedsDisplay() - } + func updateLabelContainer() { + labelContainer.layoutIfNeeded() + let radius = sizeObject.getValueBasedOnApplicationWidth()/2 - lineWidth() + let labelheight = labelContainer.frame.height/2 + let padding = sizeObject.getValueBasedOnApplicationWidth()/2 - sqrt(pow(radius, 2) - pow(labelheight, 2)) + + labelContainer.leftPin?.constant = padding + labelContainer.topPin?.constant = padding + labelContainer.setNeedsDisplay() + } } From 00d78cfdedcdf238466c35c6fea4852cac6da925 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 15 Jan 2020 13:53:54 -0500 Subject: [PATCH 30/59] update label frame --- MVMCoreUI/Molecules/DoughnutChart.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Molecules/DoughnutChart.swift b/MVMCoreUI/Molecules/DoughnutChart.swift index d58dc7c4..e6a169f1 100644 --- a/MVMCoreUI/Molecules/DoughnutChart.swift +++ b/MVMCoreUI/Molecules/DoughnutChart.swift @@ -20,9 +20,9 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { var labelContainer = ViewConstrainingView.empty() var heightConstraint: NSLayoutConstraint? - private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 150)! + private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 100)! - var height: CGFloat = 150 { + var height: CGFloat = 100 { didSet { if height != oldValue { sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: height)! @@ -174,14 +174,14 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { } func updateLabelContainer() { + labelContainer.setNeedsDisplay() labelContainer.layoutIfNeeded() let radius = sizeObject.getValueBasedOnApplicationWidth()/2 - lineWidth() let labelheight = labelContainer.frame.height/2 let padding = sizeObject.getValueBasedOnApplicationWidth()/2 - sqrt(pow(radius, 2) - pow(labelheight, 2)) labelContainer.leftPin?.constant = padding - labelContainer.topPin?.constant = padding - labelContainer.setNeedsDisplay() + labelContainer.topPin?.constant = max(radius - labelheight, labelheight) } } From e5accc7611d5f836e2793c9e3205ca536822b574 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 15 Jan 2020 13:54:31 -0500 Subject: [PATCH 31/59] update height --- MVMCoreUI/Molecules/DoughnutChart.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Molecules/DoughnutChart.swift b/MVMCoreUI/Molecules/DoughnutChart.swift index e6a169f1..1175a563 100644 --- a/MVMCoreUI/Molecules/DoughnutChart.swift +++ b/MVMCoreUI/Molecules/DoughnutChart.swift @@ -20,9 +20,9 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { var labelContainer = ViewConstrainingView.empty() var heightConstraint: NSLayoutConstraint? - private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 100)! + private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 150)! - var height: CGFloat = 100 { + var height: CGFloat = 150 { didSet { if height != oldValue { sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: height)! From e95afdc2491ba00193122adc00ed02172f4e9d74 Mon Sep 17 00:00:00 2001 From: "Pan, Xinlei (Ryan)" Date: Wed, 15 Jan 2020 16:36:13 -0500 Subject: [PATCH 32/59] update color --- MVMCoreUI/Atoms/Views/GraphView.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/GraphView.swift b/MVMCoreUI/Atoms/Views/GraphView.swift index cda77660..1f6ea45b 100644 --- a/MVMCoreUI/Atoms/Views/GraphView.swift +++ b/MVMCoreUI/Atoms/Views/GraphView.swift @@ -112,7 +112,9 @@ import UIKit //if number of colors is even, need to display gradient layer, otherwise make top layer as solid color layer if graphObject.colors.count % 2 == 0 { leftColors.removeLast() - topLayer.colors = [leftColors.last!, rightColors.first!] + let firstColor = leftColors.last!.uiColor.cgColor + let secondColor = rightColors.first!.uiColor.cgColor + topLayer.colors = [firstColor, secondColor] } else { topLayer.backgroundColor = leftColors.last?.uiColor.cgColor } @@ -125,7 +127,9 @@ import UIKit //count of graidentLayer.colors must be bigger than 1, otherwise set backgroundColor if leftColors.count > 1 { - leftLayer.colors = Array(leftColors) + leftLayer.colors = leftColors.map({ (color) -> CGColor in + return color.uiColor.cgColor + }) } else { leftLayer.backgroundColor = leftColors.first?.uiColor.cgColor } @@ -136,7 +140,9 @@ import UIKit rightLayer.startPoint = CGPoint(x: 0, y: 0) rightLayer.endPoint = CGPoint(x: 0, y: 1) if rightColors.count > 1 { - rightLayer.colors = Array(rightColors) + rightLayer.colors = rightColors.map({ (color) -> CGColor in + return color.uiColor.cgColor + }) } else { rightLayer.backgroundColor = rightColors.first?.uiColor.cgColor } From d69dbc41d00229c4c7d57a29ac9682a047ae5511 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 15 Jan 2020 18:27:56 -0500 Subject: [PATCH 33/59] fixes --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++++ .../Atoms/Views/MVMCoreUISwitch+Model.swift | 2 +- MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m | 8 +++---- MVMCoreUI/Atoms/Views/Toggle.swift | 9 +++++++ MVMCoreUI/Atoms/Views/ToggleModel.swift | 24 ++++++++++++++----- .../TwoButtonView.swift | 4 ++-- .../SwitchMolecules/LabelSwitch.swift | 12 ++++++++-- .../SwitchMolecules/LabelToggleModel.swift | 16 +++++++++++++ .../OtherHandlers/MoleculeObjectMapping.swift | 2 ++ 9 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelToggleModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 022ed193..5d855ab3 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -50,6 +50,7 @@ 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; }; 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; }; + 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C851D223CF9E740021F976 /* LabelToggleModel.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 01EB3684236097C0006832FA /* MoleculeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeProtocol.swift */; }; 01EB368F23609801006832FA /* LabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368823609801006832FA /* LabelModel.swift */; }; @@ -333,6 +334,7 @@ 0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; 0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = ""; }; 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; + 01C851D223CF9E740021F976 /* LabelToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggleModel.swift; sourceTree = ""; }; 01EB3683236097C0006832FA /* MoleculeProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeProtocol.swift; sourceTree = ""; }; 01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = ""; }; 01EB368923609801006832FA /* ListItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListItemModel.swift; sourceTree = ""; }; @@ -756,6 +758,7 @@ children = ( 01509D942327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift */, D22479892314445E003FCCF9 /* LabelSwitch.swift */, + 01C851D223CF9E740021F976 /* LabelToggleModel.swift */, D224798B231450C8003FCCF9 /* HeadlineBodySwitch.swift */, ); path = SwitchMolecules; @@ -1438,6 +1441,7 @@ 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */, D29DF17C21E69E1F003B2FB9 /* MFTextButton.m in Sources */, 9445891F2385D2E900DE9FD4 /* CaretViewModel.swift in Sources */, + 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */, D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift index 68482f09..e62a8b94 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift +++ b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift @@ -17,7 +17,7 @@ extension MVMCoreUISwitch: ModelMoleculeViewProtocol { FormValidator.setupValidation(molecule: castSelf, delegate: delegateObject?.formValidationProtocol) } - setState(model.on, animated: false) + setState(model.state, animated: false) guard let action = model.action else { return } actionBlock = { diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m index 4b66d519..1c40bc5a 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m @@ -423,16 +423,16 @@ const CGFloat SwitchShakeIntensity = 2; return UIAccessibilityTraitButton; } -- (NSString * _Nullable)formFieldGroupName { - return [self.json string:@"groupName"]; -} - - (NSString *)accessibilityHint { return [MVMCoreUIUtility hardcodedStringWithKey:@"AccToggleHint"]; } #pragma mark FormValidationProtocol +- (NSString * _Nullable)formFieldGroupName { + return [self.json string:@"groupName"]; +} + - (BOOL)isValidField { return self.isOn && [self.json boolForKey:@"required"]; } diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index 17d286ac..4e855532 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -332,6 +332,15 @@ public typealias ActionBlockConfirmation = () -> (Bool) layoutIfNeeded() } } + + public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let toggleModel = model as? ToggleModel else { + return + } + + let toggleModelJSON = toggleModel.toJSON() + setWithJSON(toggleModelJSON, delegateObject: delegateObject, additionalData: additionalData) + } } // MARK: - Accessibility diff --git a/MVMCoreUI/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atoms/Views/ToggleModel.swift index df7d2ba8..81602c2a 100644 --- a/MVMCoreUI/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atoms/Views/ToggleModel.swift @@ -10,32 +10,44 @@ import UIKit public class ToggleModel: MoleculeProtocol { public static var identifier: String = "toggle" + public var moleculeName: String? public var backgroundColor: Color? - public var on: Bool = true + public var state: Bool = true public var action: ActionProtocol? + public var required: Bool? + public var fieldKey: String? enum CodingKeys: String, CodingKey { - case on + case moleculeName + case state case action case backgroundColor + case required + case fieldKey } - public init(_ on: Bool) { - self.on = on + public init(_ state: Bool) { + self.state = state } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - if let on = try typeContainer.decodeIfPresent(Bool.self, forKey: .on) { - self.on = on + if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { + self.state = state } action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) + fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModelIfPresent(action, forKey: .action) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(state, forKey: .state) + try container.encodeIfPresent(required, forKey: .required) + try container.encodeIfPresent(fieldKey, forKey: .fieldKey) } } diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index b2f43529..9a7bd952 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -297,8 +297,8 @@ extension TwoButtonView { } } -extension TwoButtonView: MoleculeViewProtocol { - func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { +extension TwoButtonView: ModelMoleculeViewProtocol { + public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let model = model as? TwoButtonViewModel else { return } setupUI(primaryButtonShowing: model.primaryButton != nil, secondaryButtonShowing: model.secondaryButton != nil) setDefaultCustom() diff --git a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift index 50c19c1d..0713d40f 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift @@ -8,9 +8,9 @@ import UIKit -@objcMembers public class LabelSwitch: ViewConstrainingView { +@objcMembers public class LabelSwitch: ViewConstrainingView, ModelMoleculeViewProtocol { let label = Label.commonLabelB1(true) - let mvmSwitch = MVMCoreUISwitch.mvmSwitchDefault() + let mvmSwitch = Toggle() // MARK: - MVMCoreViewProtocol open override func updateView(_ size: CGFloat) { @@ -40,6 +40,14 @@ import UIKit label.setWithJSON(json?.optionalDictionaryForKey("label"), delegateObject: delegateObject, additionalData: additionalData) mvmSwitch.setWithJSON(json?.optionalDictionaryForKey("toggle"), delegateObject: delegateObject, additionalData: additionalData) } + + public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let labelToggleModel = model as? LabelToggleModel else { + return + } + label.setWithModel(labelToggleModel.label, delegateObject, additionalData) + mvmSwitch.setWithModel(labelToggleModel.toggle, delegateObject, additionalData) + } public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { return MVMCoreUISwitch.estimatedHeight(forRow: json, delegateObject: delegateObject) diff --git a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelToggleModel.swift new file mode 100644 index 00000000..6ac592d6 --- /dev/null +++ b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelToggleModel.swift @@ -0,0 +1,16 @@ +// +// LabelToggle.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 1/15/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class LabelToggleModel: MoleculeProtocol { + public static var identifier: String = "labelToggle" + public var backgroundColor: Color? + public var label: LabelModel + public var toggle: ToggleModel +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 1a041e2c..d84f48b7 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -12,6 +12,7 @@ import Foundation public static func registerObjects() { ModelRegistry.register(LabelModel.self) ModelRegistry.register(HeaderModel.self) + ModelRegistry.register(FooterModel.self) ModelRegistry.register(HeadlineBodyModel.self) ModelRegistry.register(MoleculeStackModel.self) ModelRegistry.register(StackItemModel.self) @@ -51,5 +52,6 @@ import Foundation ModelRegistry.register(LeftRightLabelModel.self) ModelRegistry.register(CaretViewModel.self) ModelRegistry.register(CaretLinkModel.self) + ModelRegistry.register(LabelToggleModel.self) } } From de27398c49de13fac16143703c90698db43fb865 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 15 Jan 2020 18:59:48 -0500 Subject: [PATCH 34/59] leftRightLabelView --- MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift index 5e091446..be703bef 100644 --- a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift +++ b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift @@ -9,7 +9,7 @@ import UIKit @objcMembers public class LeftRightLabelModel: MoleculeProtocol { - public static var identifier: String = "leftRightLabel" + public static var identifier: String = "leftRightLabelView" public var backgroundColor: Color? public var leftText: LabelModel public var rightText: LabelModel From 9bf9d711951dc078eab2b1268f2ae28e2f5fe2b1 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 16 Jan 2020 13:30:30 -0500 Subject: [PATCH 35/59] optional --- MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift | 2 +- .../VerticalCombinationViews/HeadlineBodyModel.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift index be703bef..73abb4d6 100644 --- a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift +++ b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift @@ -12,5 +12,5 @@ import UIKit public static var identifier: String = "leftRightLabelView" public var backgroundColor: Color? public var leftText: LabelModel - public var rightText: LabelModel + public var rightText: LabelModel? } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index 6ce51d3e..bc63c12c 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -10,8 +10,8 @@ import Foundation @objcMembers public class HeadlineBodyModel: MoleculeProtocol { public static var identifier: String = "headlineBody" - public var headline: LabelModel - public var body: LabelModel + public var headline: LabelModel? + public var body: LabelModel? public var style: String? public var backgroundColor: Color? From 71efaa9026dd839c0af64a1c3e8220e4c4907354 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 16 Jan 2020 13:51:55 -0500 Subject: [PATCH 36/59] alignment --- MVMCoreUI/Organisms/MoleculeStackView.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index 9f2f526f..aad48bd0 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -107,8 +107,6 @@ open class MoleculeStackView: Container { } restack() - stackModel?.useHorizontalMargins = moleculesShouldSetHorizontalMargins - stackModel?.useVerticalMargins = moleculesShouldSetVerticalMargins } open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { From b876d81922373bda1a1ecabe0ca8fea1aa3aa6bf Mon Sep 17 00:00:00 2001 From: "Pan, Xinlei (Ryan)" Date: Thu, 16 Jan 2020 14:29:30 -0500 Subject: [PATCH 37/59] two button view's internal spacing constraint change for a huge height bug --- .../TwoButtonView.swift | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 9a7bd952..10a41daa 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -84,17 +84,19 @@ import UIKit } open func setupConstraintsForViewWithButtons() { - guard let viewForButtons = viewForButtons, let primaryButton = primaryButton, let secondaryButton = secondaryButton else { - return - } + guard let viewForButtons = viewForButtons, + let primaryButton = primaryButton, + let secondaryButton = secondaryButton + else { return } + viewForButtons.addSubview(primaryButton) viewForButtons.addSubview(secondaryButton) secondaryButton.widthAnchor.constraint(equalTo: primaryButton.widthAnchor, multiplier: 1).isActive = true - secondaryButton.topAnchor.constraint(equalTo: viewForButtons.topAnchor).isActive = true - primaryButton.topAnchor.constraint(equalTo: viewForButtons.topAnchor).isActive = true - viewForButtons.bottomAnchor.constraint(equalTo: secondaryButton.bottomAnchor).isActive = true - viewForButtons.bottomAnchor.constraint(equalTo: primaryButton.bottomAnchor).isActive = true - NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[leftButton]-10-[rightButton]-0-|", options: NSLayoutConstraint.FormatOptions.alignAllCenterY, metrics: nil, views: ["leftButton": secondaryButton, "rightButton": primaryButton])) + NSLayoutConstraint.constraintPinSubview(primaryButton, pinTop: true, pinBottom: true, pinLeft: true, pinRight: false) + NSLayoutConstraint.constraintPinSubview(secondaryButton, pinTop: false, pinBottom: false, pinLeft: false, pinRight: true) + let constraint = secondaryButton.leadingAnchor.constraint(equalTo: primaryButton.trailingAnchor, constant: 10) + constraint.priority = UILayoutPriority(900) + constraint.isActive = true } func setupWithTwoButtons() { @@ -107,7 +109,6 @@ import UIKit pinView(toSuperView: viewForButtons) alignCenterHorizontal() - createPrimaryButton() createSecondaryButton() setupConstraintsForViewWithButtons() From db0d9f43531d19da30b7991a081e738133735d51 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 16 Jan 2020 14:59:24 -0500 Subject: [PATCH 38/59] Container protocol Doughnut chart model Break stack into regular and dynamic components --- MVMCoreUI.xcodeproj/project.pbxproj | 65 +++-- MVMCoreUI/Containers/Container.swift | 15 +- MVMCoreUI/Containers/ContainerProtocol.swift | 15 ++ .../{ => Doughnut}/DoughnutChart.swift | 80 +++--- .../Doughnut}/DoughnutChartModel.swift | 22 +- .../{ => Doughnut}/DoughnutChartView.swift | 103 ++++--- .../Molecules/Items/MoleculeStackItem.swift | 16 ++ .../Items/MoleculeStackItemModel.swift | 45 ++++ MVMCoreUI/Molecules/Items/StackItem.swift | 8 +- .../Molecules/Items/StackItemModel.swift | 39 +-- .../Items/StackItemModelProtocol.swift | 15 ++ .../EyebrowHeadlineBodyLink.swift | 25 +- MVMCoreUI/Organisms/MoleculeStackModel.swift | 10 +- MVMCoreUI/Organisms/MoleculeStackView.swift | 252 +----------------- MVMCoreUI/Organisms/Stack.swift | 239 +++++++++++++++++ MVMCoreUI/Organisms/StackModel.swift | 22 ++ MVMCoreUI/Organisms/StackModelProtocol.swift | 18 ++ .../MVMCoreUIMoleculeMappingObject.m | 1 - .../OtherHandlers/MoleculeObjectMapping.swift | 4 +- .../Templates/MoleculeStackTemplate.swift | 4 +- .../NSLayoutConstraintAxis+Extension.swift | 31 +++ 21 files changed, 602 insertions(+), 427 deletions(-) create mode 100644 MVMCoreUI/Containers/ContainerProtocol.swift rename MVMCoreUI/Molecules/{ => Doughnut}/DoughnutChart.swift (65%) rename MVMCoreUI/{Models/Molecules => Molecules/Doughnut}/DoughnutChartModel.swift (50%) rename MVMCoreUI/Molecules/{ => Doughnut}/DoughnutChartView.swift (55%) create mode 100644 MVMCoreUI/Molecules/Items/MoleculeStackItem.swift create mode 100644 MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift create mode 100644 MVMCoreUI/Molecules/Items/StackItemModelProtocol.swift create mode 100644 MVMCoreUI/Organisms/Stack.swift create mode 100644 MVMCoreUI/Organisms/StackModel.swift create mode 100644 MVMCoreUI/Organisms/StackModelProtocol.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 32d9b7ba..e2e09a72 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -105,10 +105,10 @@ 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */; }; 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */; }; C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; }; - C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */; }; C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69323C9909000BFB94E /* DoughnutChartModel.swift */; }; C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69523C990BC00BFB94E /* DoughnutChart.swift */; }; C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69723C990C200BFB94E /* DoughnutChartView.swift */; }; + C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; }; @@ -128,10 +128,17 @@ D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; }; D260105323CEA61600764D80 /* ToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105223CEA61600764D80 /* ToggleModel.swift */; }; D260105523CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105423CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift */; }; + D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105823D0A92900764D80 /* ContainerProtocol.swift */; }; + D260105B23D0BB7100764D80 /* StackModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105A23D0BB7100764D80 /* StackModelProtocol.swift */; }; + D260105D23D0BCD400764D80 /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105C23D0BCD400764D80 /* Stack.swift */; }; + D260105F23D0BFFC00764D80 /* StackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105E23D0BFFC00764D80 /* StackItem.swift */; }; + D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260106023D0C02A00764D80 /* StackItemModelProtocol.swift */; }; + D260106323D0C05000764D80 /* StackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260106223D0C05000764D80 /* StackItemModel.swift */; }; + D260106523D0CEA700764D80 /* StackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260106423D0CEA700764D80 /* StackModel.swift */; }; D260D7B122D65BDD007E7233 /* MVMCoreUIPageControl.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */; settings = {ATTRIBUTES = (Public, ); }; }; D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */; }; D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D268C70C2386DFFD007F2C1C /* StackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* StackItemModel.swift */; }; + D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; }; D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; }; D268C712238D6699007F2C1C /* DropDown.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C711238D6699007F2C1C /* DropDown.swift */; }; D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* StandardFooterView.swift */; }; @@ -282,7 +289,7 @@ D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; }; D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; }; D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */; }; - D2FB151D23A40F1500C20E10 /* StackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151C23A40F1500C20E10 /* StackItem.swift */; }; + D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */; }; DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; }; DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; }; DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; }; @@ -338,7 +345,7 @@ 01EB3683236097C0006832FA /* MoleculeProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeProtocol.swift; sourceTree = ""; }; 01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = ""; }; 01EB368923609801006832FA /* ListItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListItemModel.swift; sourceTree = ""; }; - 01EB368A23609801006832FA /* StackItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackItemModel.swift; sourceTree = ""; }; + 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackItemModel.swift; sourceTree = ""; }; 01EB368B23609801006832FA /* MoleculeStackModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackModel.swift; sourceTree = ""; }; 01EB368C23609801006832FA /* HeaderModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderModel.swift; sourceTree = ""; }; 01EB368D23609801006832FA /* HeadlineBodyModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyModel.swift; sourceTree = ""; }; @@ -380,10 +387,10 @@ 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeImageModel.swift; sourceTree = ""; }; 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeActionModel.swift; sourceTree = ""; }; C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; - C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadLineBodyCaretLinkImage.swift; sourceTree = ""; }; C695A69323C9909000BFB94E /* DoughnutChartModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChartModel.swift; sourceTree = ""; }; C695A69523C990BC00BFB94E /* DoughnutChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChart.swift; sourceTree = ""; }; C695A69723C990C200BFB94E /* DoughnutChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChartView.swift; sourceTree = ""; }; + C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadLineBodyCaretLinkImage.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = ""; }; @@ -403,6 +410,13 @@ D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; D260105223CEA61600764D80 /* ToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleModel.swift; sourceTree = ""; }; D260105423CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUISwitch+Model.swift"; sourceTree = ""; }; + D260105823D0A92900764D80 /* ContainerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerProtocol.swift; sourceTree = ""; }; + D260105A23D0BB7100764D80 /* StackModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackModelProtocol.swift; sourceTree = ""; }; + D260105C23D0BCD400764D80 /* Stack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stack.swift; sourceTree = ""; }; + D260105E23D0BFFC00764D80 /* StackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackItem.swift; sourceTree = ""; }; + D260106023D0C02A00764D80 /* StackItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackItemModelProtocol.swift; sourceTree = ""; }; + D260106223D0C05000764D80 /* StackItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackItemModel.swift; sourceTree = ""; }; + D260106423D0CEA700764D80 /* StackModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackModel.swift; sourceTree = ""; }; D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPageControl.h; sourceTree = ""; }; D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIPageControl.m; sourceTree = ""; }; D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = ""; }; @@ -572,7 +586,7 @@ D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = ""; }; D2F4DDE52371A4CB00CD28BB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainer.swift; sourceTree = ""; }; - D2FB151C23A40F1500C20E10 /* StackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackItem.swift; sourceTree = ""; }; + D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackItem.swift; sourceTree = ""; }; DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeftRightLabelView.swift; sourceTree = ""; }; DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = ""; }; @@ -665,10 +679,6 @@ 01EB368723609801006832FA /* Molecules */ = { isa = PBXGroup; children = ( - C695A69323C9909000BFB94E /* DoughnutChartModel.swift */, - 01EB368923609801006832FA /* ListItemModel.swift */, - 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */, - 01EB368B23609801006832FA /* MoleculeStackModel.swift */, 011B58F323A2CCC80085F53C /* DropDownModel.swift */, 01EB368C23609801006832FA /* HeaderModel.swift */, 012A88EB238F084D00FE3DA1 /* FooterModel.swift */, @@ -806,6 +816,9 @@ D22479902316A9CB003FCCF9 /* Organisms */ = { isa = PBXGroup; children = ( + D260105A23D0BB7100764D80 /* StackModelProtocol.swift */, + D260106423D0CEA700764D80 /* StackModel.swift */, + D260105C23D0BCD400764D80 /* Stack.swift */, 01EB368B23609801006832FA /* MoleculeStackModel.swift */, D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */, D2A6390022CBB1820052ED1F /* Carousel.swift */, @@ -826,8 +839,11 @@ D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */, 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */, D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */, - 01EB368A23609801006832FA /* StackItemModel.swift */, - D2FB151C23A40F1500C20E10 /* StackItem.swift */, + D260106023D0C02A00764D80 /* StackItemModelProtocol.swift */, + D260106223D0C05000764D80 /* StackItemModel.swift */, + D260105E23D0BFFC00764D80 /* StackItem.swift */, + 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */, + D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */, ); path = Items; sourceTree = ""; @@ -841,6 +857,16 @@ path = Legacy; sourceTree = ""; }; + D260105723CF9CC500764D80 /* Doughnut */ = { + isa = PBXGroup; + children = ( + C695A69323C9909000BFB94E /* DoughnutChartModel.swift */, + C695A69523C990BC00BFB94E /* DoughnutChart.swift */, + C695A69723C990C200BFB94E /* DoughnutChartView.swift */, + ); + path = Doughnut; + sourceTree = ""; + }; D29DF0C221E404D4003B2FB9 = { isa = PBXGroup; children = ( @@ -937,8 +963,7 @@ D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */, 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */, - C695A69523C990BC00BFB94E /* DoughnutChart.swift */, - C695A69723C990C200BFB94E /* DoughnutChartView.swift */, + D260105723CF9CC500764D80 /* Doughnut */, ); path = Molecules; sourceTree = ""; @@ -986,6 +1011,7 @@ D29DF2B721E7BE79003B2FB9 /* TabBarController */, D29DF2B621E7BE66003B2FB9 /* SplitViewController */, D2B18B93236214AD00A9AEDC /* NavigationController.swift */, + D260105823D0A92900764D80 /* ContainerProtocol.swift */, D243859823A16B1800332775 /* Container.swift */, ); path = Containers; @@ -1424,7 +1450,7 @@ 94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, - D2FB151D23A40F1500C20E10 /* StackItem.swift in Sources */, + D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */, 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */, @@ -1449,6 +1475,7 @@ D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, + D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */, 0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */, D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, @@ -1465,6 +1492,7 @@ D28A838723CCCF6500DFE4FC /* MFTextButton+ModelExtension.swift in Sources */, C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, + D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */, 012A88C4238D86E600FE3DA1 /* CollectionCellMoleculeProtocol.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, 014AA73123C5059B006F3E93 /* ListPageTemplateModel.swift in Sources */, @@ -1486,7 +1514,7 @@ D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */, 01EB369023609801006832FA /* ListItemModel.swift in Sources */, D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */, - D268C70C2386DFFD007F2C1C /* StackItemModel.swift in Sources */, + D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, 01509D952327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift in Sources */, @@ -1504,6 +1532,7 @@ D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */, D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */, D282AACB2243C61700C46919 /* ButtonView.swift in Sources */, + D260105D23D0BCD400764D80 /* Stack.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, 01EB368F23609801006832FA /* LabelModel.swift in Sources */, 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, @@ -1559,9 +1588,11 @@ D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */, D243859923A16B1800332775 /* Container.swift in Sources */, + D260105B23D0BB7100764D80 /* StackModelProtocol.swift in Sources */, D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */, D28A839323CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift in Sources */, D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */, + D260105F23D0BFFC00764D80 /* StackItem.swift in Sources */, 01EB369323609801006832FA /* HeaderModel.swift in Sources */, D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, 0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */, @@ -1601,6 +1632,7 @@ 014AA72E23C5059B006F3E93 /* StackCenteredPageTemplateModel.swift in Sources */, 0ABD136B237B193A0081388D /* EntryFieldContainer.swift in Sources */, D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */, + D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */, C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */, D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */, 012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */, @@ -1616,6 +1648,7 @@ D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */, 946EE1BA237B66D80036751F /* MoleculeModelHelper.swift in Sources */, 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */, + D260106523D0CEA700764D80 /* StackModel.swift in Sources */, D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/MVMCoreUI/Containers/Container.swift b/MVMCoreUI/Containers/Container.swift index ab495b81..43fd62c8 100644 --- a/MVMCoreUI/Containers/Container.swift +++ b/MVMCoreUI/Containers/Container.swift @@ -196,7 +196,7 @@ public class ContainerHelper: NSObject { } } -open class Container: View { +open class Container: View, ContainerProtocol { var view: UIView? let containerHelper = ContainerHelper() var containerModel: ContainerModelProtocol? { @@ -208,6 +208,19 @@ open class Container: View { guard let containerModel = model as? ContainerModelProtocol else { return } containerHelper.set(with: containerModel, for: view as? MVMCoreUIViewConstrainingProtocol) } + + // MARK:- ContainerProtocol + public func alignHorizontal(_ alignment: UIStackView.Alignment) { + containerHelper.alignHorizontal(alignment) + } + + public func alignVertical(_ alignment: UIStackView.Alignment) { + containerHelper.alignVertical(alignment) + } + + public func constrainView(_ view: UIView) { + containerHelper.constrainView(view) + } } // MARK: - MVMCoreViewProtocol diff --git a/MVMCoreUI/Containers/ContainerProtocol.swift b/MVMCoreUI/Containers/ContainerProtocol.swift new file mode 100644 index 00000000..8079ca24 --- /dev/null +++ b/MVMCoreUI/Containers/ContainerProtocol.swift @@ -0,0 +1,15 @@ +// +// ContainerProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/16/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol ContainerProtocol { + func alignHorizontal(_ alignment: UIStackView.Alignment) + func alignVertical(_ alignment: UIStackView.Alignment) + func constrainView(_ view: UIView) +} diff --git a/MVMCoreUI/Molecules/DoughnutChart.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift similarity index 65% rename from MVMCoreUI/Molecules/DoughnutChart.swift rename to MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift index d7f25ac6..5b0763e6 100644 --- a/MVMCoreUI/Molecules/DoughnutChart.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift @@ -8,21 +8,23 @@ import UIKit -open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { - - var containerView = MVMCoreUICommonViewsUtility.commonView() - var containerLayer = CALayer() +open class DoughnutChart: View { + var doughnutLayer = CALayer() var titleLabel = Label.commonLabelH3(true) var subTitleLabel = Label.commonLabelB2(true) var doughnutChartModel: DoughnutChartModel? { get { return model as? DoughnutChartModel } } - var labelContainer = ViewConstrainingView.empty() + var labelContainer = MVMCoreUICommonViewsUtility.commonView() + var labelContainerLeftConstraint: NSLayoutConstraint? + var labelContainerTopConstraint: NSLayoutConstraint? + var labelContainerBottomConstraint: NSLayoutConstraint? + var labelContainerRightConstraint: NSLayoutConstraint? var heightConstraint: NSLayoutConstraint? - private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 150)! - - var height: CGFloat = 150 { + static let heightConstant: CGFloat = 150 + private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: heightConstant)! + var height: CGFloat = heightConstant { didSet { if height != oldValue { sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: height)! @@ -47,17 +49,16 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { clearLayers() } - public override func setAsMolecule() { + public override func setAsMolecule() { titleLabel.setAsMolecule() subTitleLabel.setAsMolecule() } open override func setupView() { super.setupView() - guard containerView.superview == nil else { + guard labelContainer.superview == nil else { return } - addSubview(containerView) addSubview(labelContainer) labelContainer.addSubview(titleLabel) @@ -68,36 +69,35 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { //Make label font size to adjust width if label content is high titleLabel.numberOfLines = 1 titleLabel.adjustsFontSizeToFitWidth = true - - containerView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - containerView.topAnchor.constraint(equalTo: topAnchor).isActive = true - bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true - trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true - containerView.layer.addSublayer(containerLayer) - heightConstraint = containerView.heightAnchor.constraint(equalToConstant: + + layer.addSublayer(doughnutLayer) + heightConstraint = heightAnchor.constraint(equalToConstant: sizeObject.getValueBasedOnApplicationWidth()) heightConstraint?.isActive = true - containerView.widthAnchor.constraint(equalTo: containerView.heightAnchor).isActive = true + widthAnchor.constraint(equalTo: heightAnchor).isActive = true - labelContainer.leftPin = labelContainer.leftAnchor.constraint(greaterThanOrEqualTo: containerView.leftAnchor, constant: lineWidth()) - labelContainer.leftPin?.isActive = true - labelContainer.topPin = labelContainer.topAnchor.constraint(greaterThanOrEqualTo: containerView.topAnchor, constant: lineWidth()) - labelContainer.topPin?.isActive = true - labelContainer.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true - labelContainer.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true + labelContainerLeftConstraint = labelContainer.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor, constant: lineWidth()) + labelContainerLeftConstraint?.isActive = true + labelContainerTopConstraint = labelContainer.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: lineWidth()) + labelContainerTopConstraint?.isActive = true + labelContainerRightConstraint = rightAnchor.constraint(greaterThanOrEqualTo: labelContainer.rightAnchor, constant: lineWidth()) + labelContainerRightConstraint?.isActive = true + labelContainerBottomConstraint = bottomAnchor.constraint(greaterThanOrEqualTo: labelContainer.bottomAnchor, constant: lineWidth()) + labelContainerBottomConstraint?.isActive = true + labelContainer.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + labelContainer.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true NSLayoutConstraint.constraintPinSubview(titleLabel, pinTop: true, pinBottom: false, pinLeft: true, pinRight: true) NSLayoutConstraint.constraintPinSubview(subTitleLabel, pinTop: false, pinBottom: true, pinLeft: true, pinRight: true) _ = NSLayoutConstraint(pinFirstView: titleLabel, toSecondView: subTitleLabel, withConstant: 0, directionVertical: true) //Rotate view for initial draw - containerLayer.transform = CATransform3DMakeRotation(1 * .pi, 0.0, 0.0, 1.0) - + doughnutLayer.transform = CATransform3DMakeRotation(1 * .pi, 0.0, 0.0, 1.0) } open override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) clearLayers() - guard let doughnutChartModel = model as? DoughnutChartModel else { + guard let doughnutChartModel = doughnutChartModel else { return } titleLabel.setWithModel(doughnutChartModel.title, delegateObject, additionalData) @@ -111,7 +111,7 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { func drawGraph() { clearLayers() let widthHeight = sizeObject.getValueBasedOnApplicationWidth() - containerLayer.frame = CGRect(x: 0, y: 0, + doughnutLayer.frame = CGRect(x: 0, y: 0, width: widthHeight, height: widthHeight) if let doughnutChart = doughnutChartModel { @@ -122,17 +122,16 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { } } - func drawBar(_ chartModel: ChartItemModel, _ prevPercent: CGFloat) -> CGFloat { + func drawBar(_ chartModel: DoughnutChartItemModel, _ prevPercent: CGFloat) -> CGFloat { let shapeLayer = CAShapeLayer() - shapeLayer.frame = containerLayer.frame + shapeLayer.frame = doughnutLayer.frame shapeLayer.lineWidth = lineWidth() shapeLayer.fillColor = nil - shapeLayer.strokeColor = UIColor.mfGet(forHex: chartModel.color).cgColor + shapeLayer.strokeColor = chartModel.color.uiColor.cgColor let arcCenter = shapeLayer.position - let radius = shapeLayer.bounds.size.width / 2.0 - lineWidth()/2.0 - //lineSizeObject.getValueBasedOnApplicationWidth() / 2.0 + let radius = shapeLayer.bounds.size.width / 2.0 - lineWidth()/2.0 let clockwise = true let value: CGFloat = chartModel.percent @@ -146,12 +145,12 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { clockwise: clockwise) shapeLayer.path = circlePath.cgPath - containerLayer.addSublayer(shapeLayer) + doughnutLayer.addSublayer(shapeLayer) return value } func clearLayers() { - containerLayer.sublayers?.forEach({ $0.removeFromSuperlayer() }) + doughnutLayer.sublayers?.forEach({ $0.removeFromSuperlayer() }) } func updateContainer() { @@ -161,7 +160,7 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { } func lineWidth() -> CGFloat { - return doughnutChartModel?.lineWidth ?? 30 + return 30 } func lineGap() -> CGFloat { @@ -174,9 +173,10 @@ open class DoughnutChart: View, MVMCoreUIViewConstrainingProtocol { } func updateLabelContainer() { - labelContainer.leftPin?.constant = lineWidth() - labelContainer.topPin?.constant = lineWidth() + labelContainerLeftConstraint?.constant = lineWidth() + labelContainerTopConstraint?.constant = lineWidth() + labelContainerRightConstraint?.constant = lineWidth() + labelContainerBottomConstraint?.constant = lineWidth() labelContainer.setNeedsDisplay() } - } diff --git a/MVMCoreUI/Models/Molecules/DoughnutChartModel.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift similarity index 50% rename from MVMCoreUI/Models/Molecules/DoughnutChartModel.swift rename to MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift index 7aab35fd..1f4098e2 100644 --- a/MVMCoreUI/Models/Molecules/DoughnutChartModel.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift @@ -13,16 +13,24 @@ import Foundation public static var identifier: String = "doughnutChart" public var title: LabelModel? public var subtitle: LabelModel? - public var sections: [ChartItemModel] - public var lineWidth: CGFloat? + public var sections: [DoughnutChartItemModel] public var spaceRequired: Bool? + + public init(sections: [DoughnutChartItemModel]) { + self.sections = sections + } } - -@objcMembers public class ChartItemModel: MoleculeProtocol { +@objcMembers public class DoughnutChartItemModel: MoleculeProtocol { public var backgroundColor: Color? + public static var identifier: String = "doughnutChartItem" public var label: LabelModel - public var percent: CGFloat - public var color: String - public static var identifier: String = "chartItem" + @Percent public var percent: CGFloat + public var color: Color + + public init(percent: CGFloat, color: Color, label: LabelModel) { + self.percent = percent + self.color = color + self.label = label + } } diff --git a/MVMCoreUI/Molecules/DoughnutChartView.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift similarity index 55% rename from MVMCoreUI/Molecules/DoughnutChartView.swift rename to MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift index a54c04d4..4893edbc 100644 --- a/MVMCoreUI/Molecules/DoughnutChartView.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift @@ -9,54 +9,48 @@ import Foundation @objcMembers open class DoughnutChartView: View { - var doughnutChart = DoughnutChart(frame: CGRect.zero) var colorLablesStack = ColorViewLabelsStack() - var container = MVMCoreUICommonViewsUtility.commonView() var doughnutChartModel: DoughnutChartModel? { get { return model as? DoughnutChartModel } } open override func setupView() { super.setupView() - guard container.superview == nil else { + guard doughnutChart.superview == nil else { return } - - addSubview(container) doughnutChart.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(doughnutChart) + addSubview(doughnutChart) colorLablesStack.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(colorLablesStack) + addSubview(colorLablesStack) - NSLayoutConstraint.constraintPinSubview(container, pinTop: true, pinBottom: true, pinLeft: true, pinRight: true) - doughnutChart.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true - doughnutChart.topAnchor.constraint(equalTo: container.topAnchor, constant: PaddingFour).isActive = true - container.bottomAnchor.constraint(greaterThanOrEqualTo: doughnutChart.bottomAnchor).isActive = true + doughnutChart.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true + doughnutChart.topAnchor.constraint(equalTo: topAnchor, constant: PaddingFour).isActive = true + bottomAnchor.constraint(greaterThanOrEqualTo: doughnutChart.bottomAnchor).isActive = true - let containerBottomAnchor = container.bottomAnchor.constraint(equalTo: doughnutChart.bottomAnchor) - containerBottomAnchor.priority = UILayoutPriority(rawValue: 200) - containerBottomAnchor.isActive = true + let doughnutBottomAnchor = bottomAnchor.constraint(equalTo: doughnutChart.bottomAnchor) + doughnutBottomAnchor.priority = UILayoutPriority(rawValue: 200) + doughnutBottomAnchor.isActive = true - let colorLablesBottomAnchor = container.bottomAnchor.constraint(equalTo: colorLablesStack.bottomAnchor) + let colorLablesBottomAnchor = bottomAnchor.constraint(equalTo: colorLablesStack.bottomAnchor) colorLablesBottomAnchor.priority = UILayoutPriority(rawValue: 204) colorLablesBottomAnchor.isActive = true let colorLablesTopAnchor = colorLablesStack.topAnchor.constraint(equalTo: doughnutChart.topAnchor) - colorLablesTopAnchor.priority = UILayoutPriority(rawValue: 204) + colorLablesTopAnchor.priority = .defaultLow colorLablesTopAnchor.isActive = true colorLablesStack.topAnchor.constraint(greaterThanOrEqualTo: doughnutChart.topAnchor).isActive = true - container.bottomAnchor.constraint(greaterThanOrEqualTo: colorLablesStack.bottomAnchor).isActive = true - container.trailingAnchor.constraint(greaterThanOrEqualTo: colorLablesStack.trailingAnchor).isActive = true + bottomAnchor.constraint(greaterThanOrEqualTo: colorLablesStack.bottomAnchor).isActive = true + trailingAnchor.constraint(equalTo: colorLablesStack.trailingAnchor).isActive = true let centerY = colorLablesStack.centerYAnchor.constraint(equalTo: doughnutChart.centerYAnchor) - centerY.priority = .defaultLow + centerY.priority = UILayoutPriority(rawValue: 500) centerY.isActive = true colorLablesStack.leadingAnchor.constraint(equalTo: doughnutChart.trailingAnchor, constant: PaddingThree).isActive = true colorLablesStack.backgroundColor = UIColor.clear - } open override func updateView(_ size: CGFloat) { @@ -67,56 +61,51 @@ import Foundation open override func reset() { super.reset() + doughnutChart.reset() colorLablesStack.reset() } open override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) - doughnutChart.clearLayers() - colorLablesStack.removeAllItemViews() + + guard let model = doughnutChartModel else { return } doughnutChart.setWithModel(model, delegateObject, additionalData) - colorLablesStack.setWithModel(model, delegateObject, additionalData) + + // Create the stack model + var stackItems: [MoleculeStackItemModel] = [] + for item in model.sections { + stackItems.append(MoleculeStackItemModel(with: item)) + } + let stack = MoleculeStackModel(molecules: stackItems) + stack.verticalAlignment = .fill + colorLablesStack.setWithModel(stack, delegateObject, additionalData) } open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - if model == nil { - let data = try! JSONSerialization.data(withJSONObject: json!) - let decoder = JSONDecoder() - let model = try! decoder.decode(DoughnutChartModel.self, from: data) - setWithModel(model, delegateObject, additionalData as? [String : AnyHashable]) - } else { - setWithModel(model, delegateObject, additionalData as? [String : AnyHashable]) - } + guard let json = json, let model = try? Self.decodeJSONToModel(json: json, type: DoughnutChartModel.self) else { return } + setWithModel(model, delegateObject, additionalData) + } +} + +extension DoughnutChartView: MVMCoreUIViewConstrainingProtocol { + open func horizontalAlignment() -> UIStackView.Alignment { + return .leading } - } class ColorViewLabelsStack: MoleculeStackView { - - var dougnutChartModel: DoughnutChartModel? - override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - let previousModel = self.dougnutChartModel - removeAllItemViews() - guard let dougnutChartModel = model as? DoughnutChartModel else { - return + override func createStackItemsFromModel(with delegate: MVMCoreUIDelegateObject?) { + guard let stackItemModels = stackModel?.molecules else { return } + for model in stackItemModels { + let view = ColorViewWithLabel() + let stackItem = MoleculeStackItem(andContain: view) + stackItem.setWithModel(model, delegate, nil) + stackItems.append(stackItem) } - var items: [StackItem]? - if previousModel?.sections.count == dougnutChartModel.sections.count { - items = stackItems - } - stackItems = [] - self.model = MoleculeStackModel(molecules: []) - for (index, chartItemModel) in dougnutChartModel.sections.enumerated() { - let colorViewWithLabel = items?[index].view as? ColorViewWithLabel ?? ColorViewWithLabel() - colorViewWithLabel.setWithModel(chartItemModel, delegateObject, additionalData) - addView(colorViewWithLabel, lastItem: index == dougnutChartModel.sections.count - 1) - } - self.dougnutChartModel = dougnutChartModel - restack() } } -class ColorViewWithLabel: View, MVMCoreUIViewConstrainingProtocol { +class ColorViewWithLabel: View { var label = Label.commonLabelB2(true) var colorView = MVMCoreUICommonViewsUtility.commonView() @@ -140,9 +129,8 @@ class ColorViewWithLabel: View, MVMCoreUIViewConstrainingProtocol { label.leadingAnchor.constraint(equalTo: colorView.trailingAnchor, constant: PaddingOne).isActive = true label.topAnchor.constraint(equalTo: topAnchor).isActive = true - trailingAnchor.constraint(greaterThanOrEqualTo: label.trailingAnchor).isActive = true + trailingAnchor.constraint(equalTo: label.trailingAnchor).isActive = true bottomAnchor.constraint(equalTo: label.bottomAnchor).isActive = true - } override func updateView(_ size: CGFloat) { @@ -163,11 +151,10 @@ class ColorViewWithLabel: View, MVMCoreUIViewConstrainingProtocol { override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) - guard let chartItemModel = model as? ChartItemModel else { + guard let chartItemModel = model as? DoughnutChartItemModel else { return } label.setWithModel(chartItemModel.label, delegateObject, additionalData) - colorView.backgroundColor = UIColor.mfGet(forHex: chartItemModel.color) + colorView.backgroundColor = chartItemModel.color.uiColor } - } diff --git a/MVMCoreUI/Molecules/Items/MoleculeStackItem.swift b/MVMCoreUI/Molecules/Items/MoleculeStackItem.swift new file mode 100644 index 00000000..d883f93e --- /dev/null +++ b/MVMCoreUI/Molecules/Items/MoleculeStackItem.swift @@ -0,0 +1,16 @@ +// +// StackItem.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 12/13/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// +// A list item that contains a molecule + +import UIKit + +open class MoleculeStackItem: MoleculeContainer { + var stackItemModel: StackItemModel? { + get { return model as? StackItemModel } + } +} diff --git a/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift b/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift new file mode 100644 index 00000000..e2ee337d --- /dev/null +++ b/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift @@ -0,0 +1,45 @@ +// +// MoleculeStackItem.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 10/4/19. +// Copyright © 2019 Suresh, Kamlesh. All rights reserved. +// + +import Foundation + +@objcMembers public class MoleculeStackItemModel: MoleculeContainerModel, MoleculeProtocol, StackItemModelProtocol { + public static var identifier: String = "stackItem" + public var backgroundColor: Color? + public var spacing: CGFloat? + public var percent: Int? + public var gone: Bool = false + + enum MoleculeStackItemCodingKeys: String, CodingKey { + case spacing + case percent + case gone + } + + public override init(with moleculeModel: MoleculeProtocol) { + super.init(with: moleculeModel) + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: MoleculeStackItemCodingKeys.self) + spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) + percent = try typeContainer.decodeIfPresent(Int.self, forKey: .percent) + if let gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone) { + self.gone = gone + } + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: MoleculeStackItemCodingKeys.self) + try container.encodeIfPresent(spacing, forKey: .spacing) + try container.encodeIfPresent(percent, forKey: .percent) + try container.encode(gone, forKey: .gone) + } +} diff --git a/MVMCoreUI/Molecules/Items/StackItem.swift b/MVMCoreUI/Molecules/Items/StackItem.swift index 59c30962..07cae3d0 100644 --- a/MVMCoreUI/Molecules/Items/StackItem.swift +++ b/MVMCoreUI/Molecules/Items/StackItem.swift @@ -2,13 +2,13 @@ // StackItem.swift // MVMCoreUI // -// Created by Scott Pfeil on 12/13/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. +// Created by Scott Pfeil on 1/16/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. // -import UIKit +import Foundation -open class StackItem: MoleculeContainer { +open class StackItem: Container { var stackItemModel: StackItemModel? { get { return model as? StackItemModel } } diff --git a/MVMCoreUI/Molecules/Items/StackItemModel.swift b/MVMCoreUI/Molecules/Items/StackItemModel.swift index d19f2401..9ab86687 100644 --- a/MVMCoreUI/Molecules/Items/StackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/StackItemModel.swift @@ -1,45 +1,20 @@ // -// MoleculeStackItem.swift +// StackItemModel.swift // MVMCoreUI // -// Created by Suresh, Kamlesh on 10/4/19. -// Copyright © 2019 Suresh, Kamlesh. All rights reserved. +// Created by Scott Pfeil on 1/16/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. // import Foundation -@objcMembers public class StackItemModel: MoleculeContainerModel, MoleculeProtocol { - public static var identifier: String = "stackItem" - public var backgroundColor: Color? +@objcMembers public class StackItemModel: StackItemModelProtocol, Codable { public var spacing: CGFloat? public var percent: Int? public var gone: Bool = false - enum MoleculeStackItemCodingKeys: String, CodingKey { - case spacing - case percent - case gone - } - - public override init(with moleculeModel: MoleculeProtocol) { - super.init(with: moleculeModel) - } - - required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: MoleculeStackItemCodingKeys.self) - spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) - percent = try typeContainer.decodeIfPresent(Int.self, forKey: .percent) - if let gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone) { - self.gone = gone - } - try super.init(from: decoder) - } - - public override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: MoleculeStackItemCodingKeys.self) - try container.encodeIfPresent(spacing, forKey: .spacing) - try container.encodeIfPresent(percent, forKey: .percent) - try container.encode(gone, forKey: .gone) + public convenience init(gone: Bool) { + self.init() + self.gone = gone } } diff --git a/MVMCoreUI/Molecules/Items/StackItemModelProtocol.swift b/MVMCoreUI/Molecules/Items/StackItemModelProtocol.swift new file mode 100644 index 00000000..2223ed39 --- /dev/null +++ b/MVMCoreUI/Molecules/Items/StackItemModelProtocol.swift @@ -0,0 +1,15 @@ +// +// StackItemModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/16/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol StackItemModelProtocol { + var spacing: CGFloat? { get set } + var percent: Int? { get set } + var gone: Bool { get set } +} diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index d5557eca..01844e07 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -19,7 +19,7 @@ struct EyebrowHeadlineBodyLinkModel: MoleculeProtocol { } @objcMembers open class EyebrowHeadlineBodyLink: Container { - let stack = MoleculeStackView(frame: .zero) + let stack = Stack(frame: .zero) let eyebrow = Label.commonLabelB3(true) let headline = Label.commonLabelB1(true) let body = Label.commonLabelB2(true) @@ -34,19 +34,7 @@ struct EyebrowHeadlineBodyLinkModel: MoleculeProtocol { guard stack.superview == nil else { return } - let eyebrowStackItem = StackItemModel(with: casteModel!.eyeBrow!) - let headlineStackItem = StackItemModel(with: casteModel!.headline!) - let bodyStackItem = StackItemModel(with: casteModel!.body!) - let linkStackItem = StackItemModel(with: casteModel!.link!) - - // To visually take into account the extra padding in the intrinsic content of a button. - linkStackItem.spacing = -6 - - let stackModel = MoleculeStackModel(molecules: [eyebrowStackItem,headlineStackItem,bodyStackItem,linkStackItem]) - stackModel.spacing = 0 - stack.model = stackModel stack.stackItems = [StackItem(andContain: eyebrow),StackItem(andContain: headline),StackItem(andContain: body),StackItem(andContain: link)] - addSubview(stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) } @@ -64,13 +52,14 @@ struct EyebrowHeadlineBodyLinkModel: MoleculeProtocol { headline.setWithModel(casteModel?.headline, delegateObject, additionalData) body.setWithModel(casteModel?.body, delegateObject, additionalData) link.setWithModel(casteModel?.link, delegateObject, additionalData) - - (stack.stackItems[0].model as? StackItemModel)?.gone = !eyebrow.hasText - (stack.stackItems[1].model as? StackItemModel)?.gone = !headline.hasText - (stack.stackItems[2].model as? StackItemModel)?.gone = !body.hasText - (stack.stackItems[3].model as? StackItemModel)?.gone = ((link.titleLabel?.text?.count) ?? 0) == 0 + + // Create a stack model to use for the internal stack. + let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText),StackItemModel(gone: !headline.hasText),StackItemModel(gone: !body.hasText),StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)]) + stackModel.spacing = 0 + stack.model = stackModel stack.restack() } + open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { guard let json = json, let model = try? Self.decodeJSONToModel(json: json, type: EyebrowHeadlineBodyLinkModel.self) else { return } setWithModel(model, delegateObject, additionalData) diff --git a/MVMCoreUI/Organisms/MoleculeStackModel.swift b/MVMCoreUI/Organisms/MoleculeStackModel.swift index 2a149e73..7136718c 100644 --- a/MVMCoreUI/Organisms/MoleculeStackModel.swift +++ b/MVMCoreUI/Organisms/MoleculeStackModel.swift @@ -5,17 +5,19 @@ // Created by Suresh, Kamlesh on 10/3/19. // Copyright © 2019 Suresh, Kamlesh. All rights reserved. // +// A stack that has a list molecule stack items. import Foundation -@objcMembers public class MoleculeStackModel: ContainerModel, MoleculeProtocol { +@objcMembers public class MoleculeStackModel: ContainerModel, MoleculeProtocol, StackModelProtocol { public static var identifier: String = "stack" public var backgroundColor: Color? - public var molecules: [StackItemModel] + public var molecules: [MoleculeStackItemModel] public var axis: NSLayoutConstraint.Axis = .vertical public var spacing: CGFloat = 16.0 + public var useStackSpacingBeforeFirstItem = false - public init(molecules: [StackItemModel]) { + public init(molecules: [MoleculeStackItemModel]) { self.molecules = molecules super.init() } @@ -29,7 +31,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: StackCodingKeys.self) - molecules = try typeContainer.decode([StackItemModel].self, forKey: .molecules) + molecules = try typeContainer.decode([MoleculeStackItemModel].self, forKey: .molecules) if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) { axis = optionalAxis } diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index 9f2f526f..2674de0a 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -8,193 +8,22 @@ import UIKit -open class MoleculeStackView: Container { - var contentView: UIView = MVMCoreUICommonViewsUtility.commonView() - var useStackSpacingBeforeFirstItem = false - var stackModel: MoleculeStackModel? { +open class MoleculeStackView: Stack { + override var stackModel: MoleculeStackModel? { get { return model as? MoleculeStackModel } } - var stackItems: [StackItem] = [] - var moleculesShouldSetHorizontalMargins = false - var moleculesShouldSetVerticalMargins = false - - // MARK: - Helpers - public func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) { - let constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: relation, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant) - constraint.priority = priority - constraint.isActive = true - } - - /// Restacks the existing items. - func restack() { - removeAllItemViews() - let stackItems = self.stackItems - self.stackItems = [] - let lastItem = stackItems.last(where: { (item) -> Bool in - return !item.stackItemModel!.gone - }) - for item in stackItems { - addStackItem(item, lastItem: item === lastItem) - } - } - - /// Removes all stack items views from the view. - func removeAllItemViews() { - for item in stackItems { - item.removeFromSuperview() - } + /// Convenience function, adds a molecule to a MoleculeStackItem to the MoleculeStack + func addMolecule(_ view: View, lastItem: Bool) { + guard let model = view.model else { return } + let stackItemModel = MoleculeStackItemModel(with: model) + let stackItem = MoleculeStackItem(andContain: view) + addView(stackItem, stackItemModel, lastItem: lastItem) } - // MARK: - Inits - public override init(frame: CGRect) { - super.init(frame: frame) - } - - public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - super.init(frame: CGRect.zero) - setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - } - - public required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - MFViewProtocol - public override func setupView() { - super.setupView() - guard contentView.superview == nil else { - return - } - MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0) - translatesAutoresizingMaskIntoConstraints = false - backgroundColor = .clear - addSubview(contentView) - containerHelper.constrainView(contentView) - contentView.setContentHuggingPriority(.defaultHigh, for: .vertical) - contentView.setContentHuggingPriority(.defaultHigh, for: .horizontal) - } - - public override func updateView(_ size: CGFloat) { - super.updateView(size) - for item in stackItems { - item.updateView(size) - } - } - - // MARK: - MVMCoreUIMoleculeViewProtocol - public override func reset() { - super.reset() - backgroundColor = .clear - for item in stackItems { - item.reset() - } - } - - public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - let previousModel = stackModel - super.setWithModel(model, delegateObject, additionalData) - removeAllItemViews() - - // If the items in the stack are different, clear them, create new ones. - if (previousModel == nil) || MoleculeStackView.nameForReuse(previousModel, delegateObject) != MoleculeStackView.nameForReuse(model, delegateObject) { - stackItems = [] - createStackItemsFromModel(with: delegateObject) - } else if let models = stackModel?.molecules { - for (index, element) in models.enumerated() { - stackItems[index].setWithModel(element, delegateObject, additionalData) - } - } - - restack() - stackModel?.useHorizontalMargins = moleculesShouldSetHorizontalMargins - stackModel?.useVerticalMargins = moleculesShouldSetVerticalMargins - } - - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - if model == nil { - let data = try! JSONSerialization.data(withJSONObject: json!) - let decoder = JSONDecoder() - let model = try! decoder.decode(MoleculeStackModel.self, from: data) - setWithModel(model, delegateObject, additionalData) - } else { - setWithModel(model, delegateObject, additionalData) - } - } - - public override class func nameForReuse(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - // This will aggregate names of molecules to make an id. - guard let model = model as? MoleculeStackModel else { - return "stack<>" - } - var name = "stack<" - for case let item in model.molecules { - if let moleculeName = item.molecule.moleculeName { - if let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? ModelMoleculeViewProtocol.Type, - let nameForReuse = moleculeClass.nameForReuse(item.molecule, delegateObject) { - name.append(nameForReuse + ",") - } else { - name.append(moleculeName + ",") - } - } - } - name.append(">") - return name - } - - public class func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? { - // This will aggregate names of molecules to make an id. - guard let molecules = molecule?.optionalArrayForKey(KeyMolecules) else { - return "stack<>" - } - var name = "stack<" - for case let item as [AnyHashable: Any] in molecules { - if let molecule = item.optionalDictionaryForKey(KeyMolecule), let moleculeName = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) { - name.append(moleculeName + ",") - } - } - name.append(">") - return name - } - - public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - guard let items = json?.optionalArrayForKey(KeyMolecules) else { - return 0 - } - let horizontal = json?.optionalStringForKey("axis") == "horizontal" - var estimatedHeight: CGFloat = 0 - for case let item as [AnyHashable: AnyHashable] in items { - if let molecule = item.optionalDictionaryForKey(KeyMolecule) { - let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.estimatedHeight?(forRow: molecule, delegateObject: delegateObject) - if !horizontal { - // Vertical stack aggregates the items - let spacing = item.optionalCGFloatForKey("spacing") ?? (estimatedHeight != 0 ? (json?.optionalCGFloatForKey("spacing") ?? 16) : 0) - estimatedHeight += ((height ?? 0) + spacing) - } else if let height = height { - // Horizontal stack takes the tallest item. - estimatedHeight = max(estimatedHeight, height) - } - } - } - return estimatedHeight - } - - public class func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let items = json?.optionalArrayForKey(KeyMolecules) else { - return nil - } - var modules: [String] = [] - for case let item as [AnyHashable: AnyHashable] in items { - if let molecule = item.optionalDictionaryForKey(KeyMolecule), let modulesForMolecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.requiredModules?(molecule, delegateObject: delegateObject, error: error) { - modules += modulesForMolecule - } - } - return modules.count > 0 ? modules : nil - } - // MARK: - Adding to stack /// Creates all of the stackItems for the stackItemModels - func createStackItemsFromModel(with delegate: MVMCoreUIDelegateObject?) { + override func createStackItemsFromModel(with delegate: MVMCoreUIDelegateObject?) { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { if let stackItem = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model, delegate) as? StackItem { @@ -202,67 +31,4 @@ open class MoleculeStackView: Container { } } } - - /// Adds the view to the stack. - func addView(_ view: View, lastItem: Bool) { - guard let model = view.model else { return } - let stackItem = StackItem(andContain: view) - stackItem.model = StackItemModel(with: model) - addStackItem(stackItem, lastItem: lastItem) - } - - /// Adds the stack item view - private func addStackItem(_ stackItem: StackItem, lastItem: Bool) { - let stackModel = self.stackModel! - let model = stackItem.stackItemModel! - guard !model.gone else { - // Gone views do not show - return - } - contentView.addSubview(stackItem) - stackItem.translatesAutoresizingMaskIntoConstraints = false - - let spacing = model.spacing ?? stackModel.spacing - let verticalAlignment = model.verticalAlignment ?? (stackItem.view as? MVMCoreUIViewConstrainingProtocol)?.verticalAlignment?() ?? (model.percent == nil && stackModel.axis == .vertical ? .fill : (stackModel.axis == .vertical ? .leading : .center)) - let horizontalAlignment = model.horizontalAlignment ?? (stackItem.view as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() ?? (stackModel.axis == .vertical || model.percent == nil ? .fill : .leading) - stackItem.containerHelper.alignHorizontal(horizontalAlignment) - stackItem.containerHelper.alignVertical(verticalAlignment) - - let first = stackItems.first { !($0.stackItemModel?.gone ?? false) } == nil - if stackModel.axis == .vertical { - if first { - pinView(stackItem, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0) - } else if let previousView = stackItems.last(where: { item in - return !item.stackItemModel!.gone - }) { - stackItem.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: spacing).isActive = true - } - pinView(stackItem, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) - pinView(contentView, toView: stackItem, attribute: .trailing, relation: .equal, priority: .required, constant: 0) - if let percent = model.percent { - stackItem.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: CGFloat(percent)/100.0).isActive = true - } - if lastItem { - pinView(contentView, toView: stackItem, attribute: .bottom, relation: .equal, priority: .required, constant: 0) - } - } else { - if first { - // First horizontal item has no spacing by default unless told otherwise. - pinView(stackItem, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0) - } else if let previousView = stackItems.last(where: { item in - return !item.stackItemModel!.gone - }) { - stackItem.leftAnchor.constraint(equalTo: previousView.rightAnchor, constant: spacing).isActive = true - } - pinView(stackItem, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0) - pinView(contentView, toView: stackItem, attribute: .bottom, relation: .equal, priority: .required, constant: 0) - if let percent = model.percent { - stackItem.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: CGFloat(percent)/100.0).isActive = true - } - if lastItem { - pinView(contentView, toView: stackItem, attribute: .right, relation: .equal, priority: .required, constant: 0) - } - } - stackItems.append(stackItem) - } } diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift new file mode 100644 index 00000000..29f9cd9f --- /dev/null +++ b/MVMCoreUI/Organisms/Stack.swift @@ -0,0 +1,239 @@ +// +// Stack.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/16/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class Stack: Container where T: StackModelProtocol { + var contentView: UIView = MVMCoreUICommonViewsUtility.commonView() + var stackModel: T? { + get { return model as? T } + } + var stackItems: [UIView] = [] + + // MARK: - Helpers + public func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) { + let constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: relation, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant) + constraint.priority = priority + constraint.isActive = true + } + + /// Restacks the existing items. + func restack() { + removeAllItemViews() + guard let stackModel = stackModel else { return } + let stackItems = self.stackItems + self.stackItems = [] + let lastItemIndex = stackModel.molecules.lastIndex(where: { (item) -> Bool in + return !item.gone + }) + for (index, view) in stackItems.enumerated() { + addView(view, stackModel.molecules[index], lastItem: lastItemIndex == index) + } + } + + /// Removes all stack items views from the view. + func removeAllItemViews() { + for item in stackItems { + item.removeFromSuperview() + } + } + + // MARK: - Inits + public override init(frame: CGRect) { + super.init(frame: frame) + } + + public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.init(frame: CGRect.zero) + setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - MFViewProtocol + public override func setupView() { + super.setupView() + guard contentView.superview == nil else { + return + } + MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0) + translatesAutoresizingMaskIntoConstraints = false + backgroundColor = .clear + addSubview(contentView) + containerHelper.constrainView(contentView) + contentView.setContentHuggingPriority(.defaultHigh, for: .vertical) + contentView.setContentHuggingPriority(.defaultHigh, for: .horizontal) + } + + public override func updateView(_ size: CGFloat) { + super.updateView(size) + for item in stackItems { + (item as? MVMCoreViewProtocol)?.updateView(size) + } + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + public override func reset() { + super.reset() + backgroundColor = .clear + for item in stackItems { + (item as? MoleculeViewProtocol)?.reset?() + } + } + + public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + let previousModel = self.model + super.setWithModel(model, delegateObject, additionalData) + removeAllItemViews() + + // If the items in the stack are different, clear them, create new ones. + if (previousModel == nil) || MoleculeStackView.nameForReuse(previousModel, delegateObject) != MoleculeStackView.nameForReuse(model, delegateObject) { + stackItems = [] + createStackItemsFromModel(with: delegateObject) + } else if let models = stackModel?.molecules { + for (index, element) in models.enumerated() { + (stackItems[index] as? ModelMoleculeViewProtocol)?.setWithModel(element as? MoleculeProtocol, delegateObject, additionalData) + } + } + + restack() + } + + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + if model == nil { + let data = try! JSONSerialization.data(withJSONObject: json!) + let decoder = JSONDecoder() + let model = try! decoder.decode(MoleculeStackModel.self, from: data) + setWithModel(model, delegateObject, additionalData) + } else { + setWithModel(model, delegateObject, additionalData) + } + } + + public override class func nameForReuse(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + // This will aggregate names of molecules to make an id. + guard let model = model as? MoleculeStackModel else { + return "stack<>" + } + var name = "stack<" + for case let item in model.molecules { + if let moleculeName = item.molecule.moleculeName { + if let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? ModelMoleculeViewProtocol.Type, + let nameForReuse = moleculeClass.nameForReuse(item.molecule, delegateObject) { + name.append(nameForReuse + ",") + } else { + name.append(moleculeName + ",") + } + } + } + name.append(">") + return name + } + + // Need to update to take into account first spacing flag + public override class func estimatedHeight(forRow molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let model = molecule as? MoleculeStackModel else { return 0 } + let horizontal = model.axis == .horizontal + var estimatedHeight: CGFloat = 0 + for case let item in model.molecules { + if item.gone { continue } + let height = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: item, delegateObject: delegateObject) ?? 0 + if !horizontal { + // Vertical stack aggregates the items + let spacing = item.spacing ?? model.spacing + estimatedHeight += (height + spacing) + } else { + // Horizontal stack takes the tallest item. + estimatedHeight = max(estimatedHeight, height) + } + } + return estimatedHeight + } + + public override class func requiredModules(_ molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let model = molecule as? MoleculeStackModel else { return nil } + var modules: [String] = [] + for case let item in model.molecules { + if let modulesForMolecule = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.requiredModules(item, delegateObject: delegateObject, error: error) { + modules += modulesForMolecule + } + } + return modules.count > 0 ? modules : nil + } + + // MARK: - Adding to stack + /// Can be subclassed to create views when we get stack item models and have no views yet + func createStackItemsFromModel(with delegate: MVMCoreUIDelegateObject?) { + } + + /// Convenience function, adds a view to a StackItem to the Stack + func addViewToItemToStack(_ view: UIView, lastItem: Bool) { + let stackItemModel = StackItemModel() + let stackItem = StackItem(andContain: view) + addView(stackItem, stackItemModel, lastItem: lastItem) + } + + /// Adds the stack item view + func addView(_ view: UIView,_ model: StackItemModelProtocol, lastItem: Bool) { + let stackModel = self.stackModel! + guard !model.gone else { + // Gone views do not show + stackItems.append(view) + return + } + contentView.addSubview(view) + view.translatesAutoresizingMaskIntoConstraints = false + + let spacing = model.spacing ?? stackModel.spacing + if let container = view as? ContainerProtocol { + let verticalAlignment = (model as? ContainerModelProtocol)?.verticalAlignment ?? (view as? MVMCoreUIViewConstrainingProtocol)?.verticalAlignment?() ?? (model.percent == nil && stackModel.axis == .vertical ? .fill : (stackModel.axis == .vertical ? .leading : .center)) + let horizontalAlignment = (model as? ContainerModelProtocol)?.horizontalAlignment ?? (view as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() ?? (stackModel.axis == .vertical || model.percent == nil ? .fill : .leading) + container.alignHorizontal(horizontalAlignment) + container.alignVertical(verticalAlignment) + } + + let first = contentView.subviews.count == 1 + if stackModel.axis == .vertical { + if first { + pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: stackModel.useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0) + } else if let previousView = stackItems.last(where: { item in + return !model.gone + }) { + view.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: spacing).isActive = true + } + pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) + pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0) + if let percent = model.percent { + view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: CGFloat(percent)/100.0).isActive = true + } + if lastItem { + pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) + } + } else { + if first { + // First horizontal item has no spacing by default unless told otherwise. + pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: stackModel.useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0) + } else if let previousView = stackItems.last(where: { item in + return !model.gone + }) { + view.leftAnchor.constraint(equalTo: previousView.rightAnchor, constant: spacing).isActive = true + } + pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0) + pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) + if let percent = model.percent { + view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: CGFloat(percent)/100.0).isActive = true + } + if lastItem { + pinView(contentView, toView: view, attribute: .right, relation: .equal, priority: .required, constant: 0) + } + } + stackItems.append(view) + } +} diff --git a/MVMCoreUI/Organisms/StackModel.swift b/MVMCoreUI/Organisms/StackModel.swift new file mode 100644 index 00000000..b647b791 --- /dev/null +++ b/MVMCoreUI/Organisms/StackModel.swift @@ -0,0 +1,22 @@ +// +// StackModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/16/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class StackModel: StackModelProtocol, MoleculeProtocol { + public static var identifier: String = "simpleStack" + public var backgroundColor: Color? + public var molecules: [StackItemModel] + @Axis public var axis: NSLayoutConstraint.Axis = .vertical + public var spacing: CGFloat = 16.0 + public var useStackSpacingBeforeFirstItem = false + + public init(molecules: [StackItemModel]) { + self.molecules = molecules + } +} diff --git a/MVMCoreUI/Organisms/StackModelProtocol.swift b/MVMCoreUI/Organisms/StackModelProtocol.swift new file mode 100644 index 00000000..b7385466 --- /dev/null +++ b/MVMCoreUI/Organisms/StackModelProtocol.swift @@ -0,0 +1,18 @@ +// +// StackModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/16/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol StackModelProtocol { + associatedtype AnyStackItemModel: StackItemModelProtocol + + var molecules: [AnyStackItemModel] { get set } + var axis: NSLayoutConstraint.Axis { get set } + var spacing: CGFloat { get set } + var useStackSpacingBeforeFirstItem: Bool { get set } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 6c3e139e..ab054232 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -31,7 +31,6 @@ @"button": PrimaryButton.class, @"link": MFTextButton.class, @"header": StandardHeaderView.class, - @"stack": MoleculeStackView.class, @"twoButtonView": TwoButtonView.class, @"footer": StandardFooterView.class, @"caretView": CaretView.class, diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 86e7ee7e..ddc2d13f 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -10,11 +10,13 @@ import Foundation @objcMembers public class MoleculeObjectMapping: NSObject { public static func registerObjects() { + MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(MoleculeStackView.self, forKey: "stack" as NSString) + ModelRegistry.register(LabelModel.self) ModelRegistry.register(HeaderModel.self) ModelRegistry.register(HeadlineBodyModel.self) ModelRegistry.register(MoleculeStackModel.self) - ModelRegistry.register(StackItemModel.self) + ModelRegistry.register(MoleculeStackItemModel.self) ModelRegistry.register(TextFieldModel.self) ModelRegistry.register(ProgressBarModel.self) ModelRegistry.register(MultiProgressBarModel.self) diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index a4f69518..03d21c6b 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -49,8 +49,8 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { } let stack = MoleculeStackView(frame: .zero) - stack.useStackSpacingBeforeFirstItem = true - stack.moleculesShouldSetHorizontalMargins = true + moleculeStackModel.useStackSpacingBeforeFirstItem = true + moleculeStackModel.useHorizontalMargins = true stack.setWithModel(moleculeStackModel, delegateObject() as? MVMCoreUIDelegateObject, nil) return stack } diff --git a/MVMCoreUI/Utility/NSLayoutConstraintAxis+Extension.swift b/MVMCoreUI/Utility/NSLayoutConstraintAxis+Extension.swift index 05d13bcd..f989e17b 100644 --- a/MVMCoreUI/Utility/NSLayoutConstraintAxis+Extension.swift +++ b/MVMCoreUI/Utility/NSLayoutConstraintAxis+Extension.swift @@ -30,6 +30,11 @@ import Foundation try container.encode(axis.rawValueString, forKey: .axis) } */ + +enum AxisError: Error { + case notAnAxis +} + extension NSLayoutConstraint.Axis: RawRepresentable { init?(rawValue: String) { @@ -54,3 +59,29 @@ extension NSLayoutConstraint.Axis: RawRepresentable { } } } + +@propertyWrapper +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 { + let typeContainer = try decoder.singleValueContainer() + let string = try typeContainer.decode(String.self) + guard let axis = NSLayoutConstraint.Axis(rawValue: string) else { + throw AxisError.notAnAxis + } + wrappedValue = axis + } + + public func encode(to encoder: Encoder) throws { + let string = wrappedValue.rawValueString + var container = encoder.singleValueContainer() + try container.encode(string) + } +} From 7d5bee5654525ed5dc7af19c73c66e65078abf5b Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 16 Jan 2020 15:51:15 -0500 Subject: [PATCH 39/59] Label fix --- MVMCoreUI/Atoms/Views/Label.swift | 17 ++++++++++++++--- .../LabelModel/LabelAttributeActionModel.swift | 11 ++++++++++- .../Molecules/Doughnut/DoughnutChart.swift | 9 ++++----- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index e5491baf..b4173add 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -244,10 +244,15 @@ public typealias ActionBlock = () -> () } if let fontStyle = labelModel.fontStyle { MFStyler.styleLabel(self, withStyle: fontStyle) + MFStyler.styleLabel(self, withStyle: fontStyle, genericScaling: false) + standardFontSize = font.pointSize } else { let fontSize = labelModel.fontSize + if let fontSize = fontSize { + standardFontSize = fontSize + } if let fontName = labelModel.fontName { - font = MFFonts.mfFont(withName: fontName, size: fontSize ?? font.pointSize) + font = MFFonts.mfFont(withName: fontName, size: fontSize ?? standardFontSize) } else if let fontSize = fontSize { font = font.withSize(fontSize) } @@ -262,9 +267,9 @@ public typealias ActionBlock = () -> () for attribute in attributes { let range = NSRange(location: attribute.location, length: attribute.length) switch attribute { - case let underLineAtt as LabelAttributeUnderlineModel: + case let _ as LabelAttributeUnderlineModel: attributedString.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range) - case let strikeAtt as LabelAttributeStrikeThroughModel: + case let _ as LabelAttributeStrikeThroughModel: attributedString.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.thick.rawValue, range: range) attributedString.addAttribute(.baselineOffset, value: 0, range: range) case let colorAtt as LabelAttributeColorModel: @@ -309,11 +314,17 @@ public typealias ActionBlock = () -> () } } case let actionAtt as LabelAttributeActionModel: + 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] { + MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) + } + } addActionAttributes(range: range, string: attributedString) default: continue } } + attributedText = attributedString originalAttributedString = attributedText hero = labelModel.hero } diff --git a/MVMCoreUI/Atoms/Views/LabelModel/LabelAttributeActionModel.swift b/MVMCoreUI/Atoms/Views/LabelModel/LabelAttributeActionModel.swift index eb5a3cd7..8dd5c562 100644 --- a/MVMCoreUI/Atoms/Views/LabelModel/LabelAttributeActionModel.swift +++ b/MVMCoreUI/Atoms/Views/LabelModel/LabelAttributeActionModel.swift @@ -12,12 +12,21 @@ class LabelAttributeActionModel: LabelAttributeModel { override public class var identifier: String { return "action" } - + var action: ActionProtocol + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) try super.init(from: decoder) } public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeModel(action, forKey: .action) + } + + private enum CodingKeys: String, CodingKey { + case action } } diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift index a3961833..acb2e9ea 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift @@ -179,10 +179,9 @@ open class DoughnutChart: View { let labelheight = labelContainer.frame.height/2 let padding = sizeObject.getValueBasedOnApplicationWidth()/2 - sqrt(pow(radius, 2) - pow(labelheight, 2)) - labelContainer.leftPin?.constant = padding - labelContainer.rightPin?.constant = padding - labelContainer.topPin?.constant = max(radius - labelheight, labelheight) - labelContainer.bottomPin?.constant = max(radius - labelheight, labelheight) + labelContainerLeftConstraint?.constant = padding + labelContainerRightConstraint?.constant = padding + labelContainerTopConstraint?.constant = max(radius - labelheight, labelheight) + labelContainerBottomConstraint?.constant = max(radius - labelheight, labelheight) } - } From cb89795b4cb78ba86fa43b40333557cebeb27413 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 16 Jan 2020 16:17:36 -0500 Subject: [PATCH 40/59] remove ! --- MVMCoreUI/Organisms/Stack.swift | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index 29f9cd9f..0fc1ca8f 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -107,12 +107,11 @@ open class Stack: Container where T: StackModelProtocol { } open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - if model == nil { - let data = try! JSONSerialization.data(withJSONObject: json!) - let decoder = JSONDecoder() - let model = try! decoder.decode(MoleculeStackModel.self, from: data) + if let model = model { setWithModel(model, delegateObject, additionalData) - } else { + } else if let json = json, + let data = try? JSONSerialization.data(withJSONObject: json), + let model = try? JSONDecoder().decode(MoleculeStackModel.self, from: data) { setWithModel(model, delegateObject, additionalData) } } @@ -182,7 +181,7 @@ open class Stack: Container where T: StackModelProtocol { /// Adds the stack item view func addView(_ view: UIView,_ model: StackItemModelProtocol, lastItem: Bool) { - let stackModel = self.stackModel! + guard let stackModel = self.stackModel else { return } guard !model.gone else { // Gone views do not show stackItems.append(view) From 36cbccd39c0e5efb0f11dcaea6d609408d9c964c Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Thu, 16 Jan 2020 16:30:05 -0500 Subject: [PATCH 41/59] update name --- MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift | 4 ++-- MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift index acb2e9ea..233ca7d7 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift @@ -135,7 +135,7 @@ open class DoughnutChart: View { let clockwise = true let value: CGFloat = chartModel.percent - let gap: CGFloat = spaceReuired() ? lineGap() : 0.0 + let gap: CGFloat = spaceRequired() ? lineGap() : 0.0 let startAngle = ((prevPercent / 100.0) * 2 * .pi) - (0.5 * .pi) let endAngle = ((value / 100.0) * 2 * .pi) + startAngle - gap let circlePath = UIBezierPath(arcCenter: arcCenter, @@ -168,7 +168,7 @@ open class DoughnutChart: View { return doughnutChartModel?.sections.count == 1 ? 0.0 : 0.05 } - func spaceReuired() -> Bool { + func spaceRequired() -> Bool { return doughnutChartModel?.spaceRequired ?? true } diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift index 4893edbc..31091796 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift @@ -50,7 +50,7 @@ import Foundation centerY.isActive = true colorLablesStack.leadingAnchor.constraint(equalTo: doughnutChart.trailingAnchor, constant: PaddingThree).isActive = true - colorLablesStack.backgroundColor = UIColor.clear + colorLablesStack.backgroundColor = .clear } open override func updateView(_ size: CGFloat) { From b1abe0810cf78c9db39df2868d5bad64483152eb Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Thu, 16 Jan 2020 16:43:16 -0500 Subject: [PATCH 42/59] put clockwise into method --- MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift index 233ca7d7..130536e4 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChart.swift @@ -132,8 +132,7 @@ open class DoughnutChart: View { let arcCenter = shapeLayer.position let radius = shapeLayer.bounds.size.width / 2.0 - lineWidth()/2.0 - let clockwise = true - + let value: CGFloat = chartModel.percent let gap: CGFloat = spaceRequired() ? lineGap() : 0.0 let startAngle = ((prevPercent / 100.0) * 2 * .pi) - (0.5 * .pi) @@ -142,7 +141,7 @@ open class DoughnutChart: View { radius: radius, startAngle: startAngle, endAngle: endAngle, - clockwise: clockwise) + clockwise: true) shapeLayer.path = circlePath.cgPath doughnutLayer.addSublayer(shapeLayer) From 3cfe5aa4237a1f6ce6bb0d05aa9c53f49a21f0da Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 16 Jan 2020 16:47:53 -0500 Subject: [PATCH 43/59] StackModel --- MVMCoreUI/Organisms/StackModel.swift | 29 +++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Organisms/StackModel.swift b/MVMCoreUI/Organisms/StackModel.swift index b647b791..deea2457 100644 --- a/MVMCoreUI/Organisms/StackModel.swift +++ b/MVMCoreUI/Organisms/StackModel.swift @@ -12,11 +12,38 @@ import Foundation public static var identifier: String = "simpleStack" public var backgroundColor: Color? public var molecules: [StackItemModel] - @Axis public var axis: NSLayoutConstraint.Axis = .vertical + public var axis: NSLayoutConstraint.Axis = .vertical public var spacing: CGFloat = 16.0 public var useStackSpacingBeforeFirstItem = false public init(molecules: [StackItemModel]) { self.molecules = molecules } + + enum StackCodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case molecules + case axis + case spacing + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: StackCodingKeys.self) + + molecules = try typeContainer.decode([StackItemModel].self, forKey: .molecules) + if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) { + axis = optionalAxis + } + if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) { + self.spacing = spacing + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: StackCodingKeys.self) + try container.encodeIfPresent(molecules, forKey: .molecules) + try container.encodeIfPresent(axis.rawValueString, forKey: .axis) + try container.encodeIfPresent(spacing, forKey: .spacing) + } } From 4dde423d2f8668e47a806eff6ed06bc9dd53f4c7 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 16 Jan 2020 17:32:00 -0500 Subject: [PATCH 44/59] button fixes --- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 7 +++++++ .../PrimaryButton+MoleculeProtocolExtension.swift | 10 ++++++++++ MVMCoreUI/Atoms/Buttons/PrimaryButton.h | 3 +++ MVMCoreUI/Atoms/Buttons/PrimaryButton.m | 2 -- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index 4329ccff..64d9a3c3 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -25,6 +25,8 @@ public class ButtonModel: MoleculeProtocol { public var action: ActionProtocol public var style: ButtonStyle? = .primary public var size: ButtonSize? = .standard + public var required: Bool? + public var requiredGroups: [String]? init(with title: String, action: ActionProtocol) { self.title = title @@ -37,6 +39,8 @@ public class ButtonModel: MoleculeProtocol { case action case style case size + case required + case requiredGroups } required public init(from decoder: Decoder) throws { @@ -44,6 +48,8 @@ public class ButtonModel: MoleculeProtocol { backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decode(String.self, forKey: .title) action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) + required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) + requiredGroups = try typeContainer.decodeIfPresent([String].self, forKey: .requiredGroups) if let style = try typeContainer.decodeIfPresent(ButtonStyle.self, forKey: .style) { self.style = style } @@ -59,5 +65,6 @@ public class ButtonModel: MoleculeProtocol { try container.encodeModel(action, forKey: .action) try container.encodeIfPresent(style, forKey: .style) try container.encodeIfPresent(size, forKey: .size) + try container.encodeIfPresent(required, forKey: .required) } } diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift index 2d7ecf40..09c94bdf 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift @@ -14,6 +14,16 @@ extension PrimaryButton: ModelMoleculeViewProtocol { guard let model = model as? ButtonModel else { return } setTitle(model.title, for: .normal) backgroundColor = model.backgroundColor?.uiColor + + self.validationRequired = model.required ?? false + self.requiredGroupsList = model.requiredGroups + + if self.validationRequired, + let selfForm = self as? FormValidationEnableDisableProtocol { + FormValidator.setupValidation(molecule: selfForm, delegate: delegateObject?.formValidationProtocol) + } + + if let style = model.style { switch style { case .primary: diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.h b/MVMCoreUI/Atoms/Buttons/PrimaryButton.h index 99929430..e83484a0 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.h +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.h @@ -46,6 +46,9 @@ static CGFloat const PrimaryButtonSmallHeight = 30.0; // set YES to skip highlight method, for customer color button @property (nonatomic) BOOL skipHighlighted; +@property (nonatomic) BOOL validationRequired; +@property (nullable, nonatomic, strong) NSArray *requiredGroupsList; + // The main creation functions, changed to black button for 2.0 for default + (nullable instancetype)primaryButton:(BOOL)enabled; + (nullable instancetype)primarySmallButton:(BOOL)enabled; diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m index 2bc9e026..439d5479 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m @@ -20,8 +20,6 @@ @interface PrimaryButton() -@property (nonatomic) BOOL validationRequired; -@property (nonatomic, strong) NSArray *requiredGroupsList; @property (nonatomic) BOOL smallButton; @property (assign, nonatomic) BOOL tinyButton; @property (nonatomic) CGFloat sizeForSizing; From 8209101b73683a59ab27cde568fee99fe0f5d230 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 16 Jan 2020 18:54:01 -0500 Subject: [PATCH 45/59] hot fix --- MVMCoreUI/Molecules/Items/MoleculeStackItem.swift | 2 +- MVMCoreUI/Organisms/MoleculeStackView.swift | 2 +- MVMCoreUI/OtherHandlers/CoreUIObject.swift | 1 + .../OtherHandlers/MVMCoreUIMoleculeMappingObject.m | 10 +--------- MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift | 3 ++- 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/MVMCoreUI/Molecules/Items/MoleculeStackItem.swift b/MVMCoreUI/Molecules/Items/MoleculeStackItem.swift index d883f93e..279e7948 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeStackItem.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeStackItem.swift @@ -1,5 +1,5 @@ // -// StackItem.swift +// MoleculeStackItem.swift // MVMCoreUI // // Created by Scott Pfeil on 12/13/19. diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index 2674de0a..a7dd1640 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -26,7 +26,7 @@ open class MoleculeStackView: Stack { override func createStackItemsFromModel(with delegate: MVMCoreUIDelegateObject?) { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { - if let stackItem = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model, delegate) as? StackItem { + if let stackItem = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model, delegate) as? MoleculeStackItem { stackItems.append(stackItem) } } diff --git a/MVMCoreUI/OtherHandlers/CoreUIObject.swift b/MVMCoreUI/OtherHandlers/CoreUIObject.swift index af0f5023..427fcfba 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIObject.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIObject.swift @@ -19,5 +19,6 @@ import UIKit viewControllerMapping = MVMCoreUIViewControllerMappingObject() loggingDelegate = MVMCoreUILoggingHandler() moleculeMap = MVMCoreUIMoleculeMappingObject() + MoleculeObjectMapping.registerObjects() } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 09c98c1a..1eda2454 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -70,10 +70,9 @@ @"tabsListItem": TabsTableViewCell.class, @"dropDownListItem": DropDownFilterTableViewCell.class, @"headlineBodyButton": HeadlineBodyButton.class, - @"stackItem": StackItem.class, + @"stackItem": MoleculeStackItem.class, @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class, @"headlineBodyCaretLinkImage" : HeadLineBodyCaretLinkImage.class, - @"stackItem": StackItem.class, @"doughnutChart": DoughnutChartView.class, @"headLineBodyCaretLinkImage" : HeadLineBodyCaretLinkImage.class } mutableCopy]; @@ -85,13 +84,6 @@ return [MVMCoreActionUtility initializerClassCheck:[CoreUIObject sharedInstance].moleculeMap classToVerify:self]; } -- (instancetype)init { - if (self = [super init]) { - [MoleculeObjectMapping registerObjects]; - } - return self; -} - - (nullable Class)getMoleculeClassWithJSON:(nonnull NSDictionary *)json { NSString *moleculeName = [json string:KeyMoleculeName]; if (moleculeName) { diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index fe4c7e11..6bcdd4cd 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -10,7 +10,8 @@ import Foundation @objcMembers public class MoleculeObjectMapping: NSObject { public static func registerObjects() { - MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(MoleculeStackView.self, forKey: "stack" as NSString) + let mapping = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping + mapping?.setObject(MoleculeStackView.self, forKey: "stack" as NSString) ModelRegistry.register(LabelModel.self) ModelRegistry.register(HeaderModel.self) From 54cc1f54261e76fb2d126bb8fb4a3f4b86815129 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 16 Jan 2020 19:48:14 -0500 Subject: [PATCH 46/59] registerModels() --- MVMCoreUI/OtherHandlers/CoreUIObject.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/OtherHandlers/CoreUIObject.swift b/MVMCoreUI/OtherHandlers/CoreUIObject.swift index 427fcfba..9d2957c2 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIObject.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIObject.swift @@ -10,7 +10,11 @@ import UIKit @objcMembers open class CoreUIObject: MVMCoreObject { public var moleculeMap: MVMCoreUIMoleculeMappingObject? - + + open func registerModels() { + MoleculeObjectMapping.registerObjects() + } + open override func defaultInitialSetup() { cache = MVMCoreCache() sessionHandler = MVMCoreSessionTimeHandler() @@ -19,6 +23,6 @@ import UIKit viewControllerMapping = MVMCoreUIViewControllerMappingObject() loggingDelegate = MVMCoreUILoggingHandler() moleculeMap = MVMCoreUIMoleculeMappingObject() - MoleculeObjectMapping.registerObjects() + registerModels() } } From d8a7efde8a727fb0f6f9849041ebacfdfd69c669 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 16 Jan 2020 20:57:17 -0500 Subject: [PATCH 47/59] undo register change --- MVMCoreUI/OtherHandlers/CoreUIObject.swift | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/MVMCoreUI/OtherHandlers/CoreUIObject.swift b/MVMCoreUI/OtherHandlers/CoreUIObject.swift index 9d2957c2..d60cdd6a 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIObject.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIObject.swift @@ -11,10 +11,6 @@ import UIKit @objcMembers open class CoreUIObject: MVMCoreObject { public var moleculeMap: MVMCoreUIMoleculeMappingObject? - open func registerModels() { - MoleculeObjectMapping.registerObjects() - } - open override func defaultInitialSetup() { cache = MVMCoreCache() sessionHandler = MVMCoreSessionTimeHandler() @@ -23,6 +19,6 @@ import UIKit viewControllerMapping = MVMCoreUIViewControllerMappingObject() loggingDelegate = MVMCoreUILoggingHandler() moleculeMap = MVMCoreUIMoleculeMappingObject() - registerModels() + MoleculeObjectMapping.registerObjects() } } From 017dc1d0020520a01d75bf887eaea9b8bbb3350d Mon Sep 17 00:00:00 2001 From: "Khan, Arshad" Date: Fri, 17 Jan 2020 21:32:49 +0530 Subject: [PATCH 48/59] secondary button top alignment fix, which was breaking all BAU secondary buttons. --- .../Molecules/HorizontalCombinationViews/TwoButtonView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 10a41daa..47e67724 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -93,7 +93,7 @@ import UIKit viewForButtons.addSubview(secondaryButton) secondaryButton.widthAnchor.constraint(equalTo: primaryButton.widthAnchor, multiplier: 1).isActive = true NSLayoutConstraint.constraintPinSubview(primaryButton, pinTop: true, pinBottom: true, pinLeft: true, pinRight: false) - NSLayoutConstraint.constraintPinSubview(secondaryButton, pinTop: false, pinBottom: false, pinLeft: false, pinRight: true) + NSLayoutConstraint.constraintPinSubview(secondaryButton, pinTop: true, pinBottom: false, pinLeft: false, pinRight: true) let constraint = secondaryButton.leadingAnchor.constraint(equalTo: primaryButton.trailingAnchor, constant: 10) constraint.priority = UILayoutPriority(900) constraint.isActive = true From 13dbb283571e42bf931a51130ff02e9b63c7a016 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 17 Jan 2020 11:04:35 -0500 Subject: [PATCH 49/59] caret title --- MVMCoreUI/Atoms/Buttons/CaretButton.swift | 2 +- MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/CaretButton.swift b/MVMCoreUI/Atoms/Buttons/CaretButton.swift index 6c8e4d31..64120043 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretButton.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretButton.swift @@ -149,7 +149,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI } isEnabled = caretLinkModel.enabled set(with: caretLinkModel.action, delegateObject: delegateObject, additionalData: additionalData) - setTitle(caretLinkModel.label.text, for: .normal) + setTitle(caretLinkModel.title, for: .normal) } public func needsToBeConstrained() -> Bool { diff --git a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift index db2de2b0..b2fc5841 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift @@ -12,20 +12,20 @@ import MVMCore public class CaretLinkModel: MoleculeProtocol { public static var identifier: String = "caretLink" public var backgroundColor: Color? - public var label: LabelModel + public var title: String public var action: ActionProtocol public var enabledColor: Color = Color(uiColor: .black) public var disabledColor: Color? = Color(uiColor: .mfSilver()) public var enabled: Bool = true - public init(label: LabelModel, action: ActionProtocol) { - self.label = label + public init(title: String, action: ActionProtocol) { + self.title = title self.action = action } enum CodingKeys: String, CodingKey { case backgroundColor - case label + case title case action case enabledColor case disabledColor @@ -35,7 +35,7 @@ public class CaretLinkModel: MoleculeProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - label = try typeContainer.decode(LabelModel.self, forKey: .label) + title = try typeContainer.decode(String.self, forKey: .title) if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor) { enabledColor = color } @@ -50,7 +50,7 @@ public class CaretLinkModel: MoleculeProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(label, forKey: .label) + try container.encode(title, forKey: .title) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModel(action, forKey: .action) try container.encode(enabled, forKey: .enabledColor) From 401370f97610d022221b350cb7df8c7c3ae2fb56 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 17 Jan 2020 12:03:31 -0500 Subject: [PATCH 50/59] toggle action --- MVMCoreUI/Atoms/Views/Toggle.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index 4e855532..366b6b89 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -398,7 +398,7 @@ extension Toggle { changeStateNoAnimation(state) } - if let actionMap = dictionary.optionalDictionaryForKey("actionMap") { + if let actionMap = dictionary.optionalDictionaryForKey("action") { didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } From 9847ef5302218e82df157a83659edcd989427832 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 17 Jan 2020 13:51:46 -0500 Subject: [PATCH 51/59] stack flexibility update molecule container protocol fix missing functions update numbered and unordered list to more model approach --- MVMCoreUI.xcodeproj/project.pbxproj | 64 +- MVMCoreUI.xcodeproj/project.pbxproj.orig | 1622 ----------------- MVMCoreUI/Containers/Container.swift | 1 + .../Models/Molecules/NumberedListModel.swift | 33 - .../Models/Molecules/UnOrderedListModel.swift | 33 - .../Doughnut/DoughnutChartView.swift | 4 +- .../Molecules/Items/StackItemModel.swift | 4 +- .../Items/StackItemModelProtocol.swift | 2 +- .../Molecules/LabelRightMoleculesStack.swift | 167 -- MVMCoreUI/Molecules/MoleculeContainer.swift | 24 + MVMCoreUI/Molecules/NumberedList.swift | 18 - MVMCoreUI/Molecules/UnOrderedList.swift | 18 - .../Lists/NumberedList.swift | 14 + .../Lists/NumberedListModel.swift | 47 + .../StringAndMoleculeModel.swift | 42 + .../StringAndMoleculeStack.swift | 28 + .../StringAndMoleculeView.swift | 92 + .../Lists/UnOrderedList.swift | 12 + .../Lists/UnOrderedListModel.swift | 51 + MVMCoreUI/Organisms/MoleculeStackModel.swift | 4 +- MVMCoreUI/Organisms/MoleculeStackView.swift | 4 +- MVMCoreUI/Organisms/Stack.swift | 44 +- .../MVMCoreUIMoleculeMappingObject.m | 2 - .../OtherHandlers/MoleculeObjectMapping.swift | 16 +- 24 files changed, 396 insertions(+), 1950 deletions(-) delete mode 100644 MVMCoreUI.xcodeproj/project.pbxproj.orig delete mode 100644 MVMCoreUI/Models/Molecules/NumberedListModel.swift delete mode 100644 MVMCoreUI/Models/Molecules/UnOrderedListModel.swift delete mode 100644 MVMCoreUI/Molecules/LabelRightMoleculesStack.swift delete mode 100644 MVMCoreUI/Molecules/NumberedList.swift delete mode 100644 MVMCoreUI/Molecules/UnOrderedList.swift create mode 100644 MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedList.swift create mode 100644 MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift create mode 100644 MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift create mode 100644 MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift create mode 100644 MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift create mode 100644 MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedList.swift create mode 100644 MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 0ab12529..11ba168e 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -107,15 +107,15 @@ 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */; }; 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */; }; C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; }; + C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */; }; + C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A68023C9830D00BFB94E /* NumberedListModel.swift */; }; C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69323C9909000BFB94E /* DoughnutChartModel.swift */; }; C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69523C990BC00BFB94E /* DoughnutChart.swift */; }; C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69723C990C200BFB94E /* DoughnutChartView.swift */; }; - C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */; }; - C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */; }; - C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A68023C9830D00BFB94E /* NumberedListModel.swift */; }; C6FA7D5223C77A4A00A3614A /* UnOrderedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D4F23C77A4700A3614A /* UnOrderedList.swift */; }; - C6FA7D5323C77A4A00A3614A /* LabelRightMoleculesStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5023C77A4800A3614A /* LabelRightMoleculesStack.swift */; }; + C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5023C77A4800A3614A /* StringAndMoleculeStack.swift */; }; C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5123C77A4900A3614A /* NumberedList.swift */; }; + C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; }; @@ -272,6 +272,8 @@ D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF32321ED0DA2003B2FB9 /* TextButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32821EE8736003B2FB9 /* Localizable.strings */; }; D29DF32E21EE8C3D003B2FB9 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */; }; + D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */; }; + D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */; }; D2A514582211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */; }; D2A5145D2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -370,9 +372,9 @@ 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; - 0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = ""; }; 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = ""; }; 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = ""; }; + 0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = ""; }; 0ABD136A237B193A0081388D /* EntryFieldContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = ""; }; 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = ""; }; 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = ""; }; @@ -396,15 +398,15 @@ 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeImageModel.swift; sourceTree = ""; }; 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeActionModel.swift; sourceTree = ""; }; C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; + C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedListModel.swift; sourceTree = ""; }; + C695A68023C9830D00BFB94E /* NumberedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberedListModel.swift; sourceTree = ""; }; C695A69323C9909000BFB94E /* DoughnutChartModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChartModel.swift; sourceTree = ""; }; C695A69523C990BC00BFB94E /* DoughnutChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChart.swift; sourceTree = ""; }; C695A69723C990C200BFB94E /* DoughnutChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChartView.swift; sourceTree = ""; }; - C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadLineBodyCaretLinkImage.swift; sourceTree = ""; }; - C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedListModel.swift; sourceTree = ""; }; - C695A68023C9830D00BFB94E /* NumberedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberedListModel.swift; sourceTree = ""; }; C6FA7D4F23C77A4700A3614A /* UnOrderedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedList.swift; sourceTree = ""; }; - C6FA7D5023C77A4800A3614A /* LabelRightMoleculesStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelRightMoleculesStack.swift; sourceTree = ""; }; + C6FA7D5023C77A4800A3614A /* StringAndMoleculeStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeStack.swift; sourceTree = ""; }; C6FA7D5123C77A4900A3614A /* NumberedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberedList.swift; sourceTree = ""; }; + C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadLineBodyCaretLinkImage.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = ""; }; @@ -575,6 +577,8 @@ D29DF32A21EE8736003B2FB9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; D29DF32B21EE8736003B2FB9 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = ""; }; D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; + D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeView.swift; sourceTree = ""; }; + D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeModel.swift; sourceTree = ""; }; D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIMoleculeMappingObject.h; sourceTree = ""; }; D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIMoleculeMappingObject.m; sourceTree = ""; }; D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIMoleculeViewProtocol.h; sourceTree = ""; }; @@ -701,8 +705,6 @@ 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */, 012A88C1238D7BCA00FE3DA1 /* CarouselItemModel.swift */, 012A88C5238DA34000FE3DA1 /* ModuleMoleculeModel.swift */, - C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */, - C695A68023C9830D00BFB94E /* NumberedListModel.swift */, ); path = Molecules; sourceTree = ""; @@ -715,7 +717,7 @@ path = Protocols; sourceTree = ""; }; - 0ABD1369237B18EE0081388D /* views */ = { + 0ABD1369237B18EE0081388D /* views */ = { isa = PBXGroup; children = ( 0ABD136A237B193A0081388D /* EntryFieldContainer.swift */, @@ -723,14 +725,6 @@ path = views; sourceTree = ""; }; - 0AA33B322398134B0067DD0F /* Primitive Models */ = { - isa = PBXGroup; - children = ( - 0AA33B35239813EE0067DD0F /* Color.swift */, - ); - path = "Primitive Models"; - sourceTree = ""; - }; 946EE1B5237B663A0036751F /* Extensions */ = { isa = PBXGroup; children = ( @@ -807,6 +801,7 @@ D224798D2316A988003FCCF9 /* VerticalCombinationViews */ = { isa = PBXGroup; children = ( + D29E28D423D1FFFA00ACEA85 /* Lists */, D2A638FC22CA98280052ED1F /* HeadlineBody.swift */, 01EB368D23609801006832FA /* HeadlineBodyModel.swift */, D22479952316AF6D003FCCF9 /* HeadlineBodyTextButton.swift */, @@ -988,9 +983,6 @@ D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */, 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */, - C6FA7D5023C77A4800A3614A /* LabelRightMoleculesStack.swift */, - C6FA7D5123C77A4900A3614A /* NumberedList.swift */, - C6FA7D4F23C77A4700A3614A /* UnOrderedList.swift */, D260105723CF9CC500764D80 /* Doughnut */, ); path = Molecules; @@ -1299,6 +1291,28 @@ path = Strings; sourceTree = ""; }; + D29E28D423D1FFFA00ACEA85 /* Lists */ = { + isa = PBXGroup; + children = ( + D29E28DB23D21B0A00ACEA85 /* StringAndMoleculeStack */, + C695A68023C9830D00BFB94E /* NumberedListModel.swift */, + C6FA7D5123C77A4900A3614A /* NumberedList.swift */, + C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */, + C6FA7D4F23C77A4700A3614A /* UnOrderedList.swift */, + ); + path = Lists; + sourceTree = ""; + }; + D29E28DB23D21B0A00ACEA85 /* StringAndMoleculeStack */ = { + isa = PBXGroup; + children = ( + D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */, + D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */, + C6FA7D5023C77A4800A3614A /* StringAndMoleculeStack.swift */, + ); + path = StringAndMoleculeStack; + sourceTree = ""; + }; D2B18B7D236090D500A9AEDC /* BaseClasses */ = { isa = PBXGroup; children = ( @@ -1543,6 +1557,7 @@ D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */, 012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */, D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */, + D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, 01EB369023609801006832FA /* ListItemModel.swift in Sources */, D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */, D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, @@ -1563,6 +1578,7 @@ D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */, D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */, D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */, + D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */, D282AACB2243C61700C46919 /* ButtonView.swift in Sources */, D260105D23D0BCD400764D80 /* Stack.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, @@ -1589,7 +1605,7 @@ 011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */, 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */, 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */, - C6FA7D5323C77A4A00A3614A /* LabelRightMoleculesStack.swift in Sources */, + C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */, diff --git a/MVMCoreUI.xcodeproj/project.pbxproj.orig b/MVMCoreUI.xcodeproj/project.pbxproj.orig deleted file mode 100644 index 2036d4b5..00000000 --- a/MVMCoreUI.xcodeproj/project.pbxproj.orig +++ /dev/null @@ -1,1622 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 48; - objects = { - -/* Begin PBXBuildFile section */ - 01004F3022721C3800991ECC /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01004F2F22721C3800991ECC /* RadioButton.swift */; }; - 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618A224BBE7700E1557D /* FormValidator.swift */; }; - 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; }; - 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; }; - 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */; }; - 012A88EE239858E300FE3DA1 /* ContainerMoleculeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88ED239858E300FE3DA1 /* ContainerMoleculeProtocol.swift */; }; - 012CA98923849699003F810F /* SeperatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA98823849699003F810F /* SeperatorModel.swift */; }; - 012CA99A2384A687003F810F /* MFTextField+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */; }; - 012CA99C23859FDC003F810F /* ViewConstrainingView+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA99B23859FDC003F810F /* ViewConstrainingView+ModelExtension.swift */; }; - 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */; }; - 012CA9BE2385C692003F810F /* ConstrainingMoleculeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9BD2385C692003F810F /* ConstrainingMoleculeProtocol.swift */; }; - 01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */; }; - 01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D902327ECE600EF99AA /* CornerLabels.swift */; }; - 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D922327ECFB00EF99AA /* ProgressBar.swift */; }; - 01509D952327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D942327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift */; }; - 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */; }; - 017BEB3A2360EEB40024EF95 /* PageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB392360EEB40024EF95 /* PageModel.swift */; }; - 017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */; }; - 017BEB4023620A230024EF95 /* TextFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB3F23620A230024EF95 /* TextFieldModel.swift */; }; - 017BEB4223620AD20024EF95 /* FormModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB4123620AD20024EF95 /* FormModelProtocol.swift */; }; - 017BEB442362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB432362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift */; }; - 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */; }; - 017BEB4A236235BA0024EF95 /* ModelMoleculeViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */; }; - 017BEB7B236763000024EF95 /* LineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB7A236763000024EF95 /* LineModel.swift */; }; - 017BEB7F23676E870024EF95 /* MoleculeObjectMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */; }; - 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; }; - 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; }; - 01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */; }; - 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; }; - 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; - 01EB3684236097C0006832FA /* MoleculeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeProtocol.swift */; }; - 01EB368F23609801006832FA /* LabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368823609801006832FA /* LabelModel.swift */; }; - 01EB369023609801006832FA /* ListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368923609801006832FA /* ListItemModel.swift */; }; - 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368B23609801006832FA /* MoleculeStackModel.swift */; }; - 01EB369323609801006832FA /* HeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368C23609801006832FA /* HeaderModel.swift */; }; - 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368D23609801006832FA /* HeadlineBodyModel.swift */; }; - 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; - 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */; }; - 0A209CD323A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */; }; - 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; - 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; - 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; - 0AA33B34239813C50067DD0F /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */; }; - 0AA33B36239813EE0067DD0F /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B35239813EE0067DD0F /* Color.swift */; }; - 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; - 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; - 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; }; - 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */; }; - 9445891F2385D2E900DE9FD4 /* CaretViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445891E2385D2E900DE9FD4 /* CaretViewModel.swift */; }; - 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944589202385D6E900DE9FD4 /* DashLineModel.swift */; }; - 944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944589222385DA9500DE9FD4 /* ImageViewModel.swift */; }; - 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; - 946EE1BA237B66D80036751F /* ModelHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946EE1B9237B66D80036751F /* ModelHelper.swift */; }; - 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; - 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */; }; - 94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */; }; - 94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A223872C110006CF46 /* LabelAttributeStrikeThroughModel.swift */; }; - 94C2D9A523872C350006CF46 /* LabelAttributeFontModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A423872C350006CF46 /* LabelAttributeFontModel.swift */; }; - 94C2D9A723872DA90006CF46 /* LabelAttributeColorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */; }; - 94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */; }; - 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */; }; - D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; - D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; - D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; }; - D224798A2314445E003FCCF9 /* LabelSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479892314445E003FCCF9 /* LabelSwitch.swift */; }; - D224798C231450C8003FCCF9 /* HeadlineBodySwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224798B231450C8003FCCF9 /* HeadlineBodySwitch.swift */; }; - D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */; }; - D22479962316AF6E003FCCF9 /* HeadlineBodyTextButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479952316AF6D003FCCF9 /* HeadlineBodyTextButton.swift */; }; - D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */; }; - D22D1F1A220341F60077CEC0 /* MVMCoreUICheckBox.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F18220341F50077CEC0 /* MVMCoreUICheckBox.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F19220341F50077CEC0 /* MVMCoreUICheckBox.m */; }; - D22D1F1E220343560077CEC0 /* MVMCoreUICheckMarkView.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F1C220343560077CEC0 /* MVMCoreUICheckMarkView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F1D220343560077CEC0 /* MVMCoreUICheckMarkView.m */; }; - D22D1F46220496A30077CEC0 /* MVMCoreUISwitch.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F44220496A30077CEC0 /* MVMCoreUISwitch.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */; }; - D22D1F562204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */; }; - D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; }; - D260D7B122D65BDD007E7233 /* MVMCoreUIPageControl.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */; }; - D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; }; - D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; }; - D268C712238D6699007F2C1C /* DropDown.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C711238D6699007F2C1C /* DropDown.swift */; }; - D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* StandardFooterView.swift */; }; - D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2755D7A23689C7500485468 /* TableViewCell.swift */; }; - D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */; }; - D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */; }; - D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */; }; - D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */; }; - D282AACB2243C61700C46919 /* ButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AACA2243C61700C46919 /* ButtonView.swift */; }; - D296E13C229598BF0051EBE7 /* MoleculeListCellProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E13B2295969C0051EBE7 /* MoleculeListCellProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D296E1412295EBBA0051EBE7 /* MoleculeDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E1402295EBBA0051EBE7 /* MoleculeDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D296E14722A5984C0051EBE7 /* MVMCoreUIViewConstrainingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */; }; - D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770EE21F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m */; }; - D29770F321F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770EF21F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29770F421F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770F021F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770F121F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m */; }; - D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */; }; - D29770FD21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */; }; - D29DF0D121E404D4003B2FB9 /* MVMCoreUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */; }; - D29DF11521E6805F003B2FB9 /* UIColor+MFConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF11621E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11221E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF11321E6805F003B2FB9 /* UIColor+MFConvenience.m */; }; - D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF11421E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m */; }; - D29DF11C21E684A9003B2FB9 /* MVMCoreUISplitViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11A21E684A9003B2FB9 /* MVMCoreUISplitViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF11B21E684A9003B2FB9 /* MVMCoreUISplitViewController.m */; }; - D29DF12921E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF12A21E6851E003B2FB9 /* MVMCoreUITopAlertView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12021E6851E003B2FB9 /* MVMCoreUITopAlertView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m */; }; - D29DF12C21E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12221E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12321E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12421E6851E003B2FB9 /* MVMCoreUITopAlertView.m */; }; - D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12521E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m */; }; - D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12621E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m */; }; - D29DF13121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12721E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12821E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m */; }; - D29DF15421E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF15321E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF15F21E69996003B2FB9 /* MFViewController.m */; }; - D29DF16221E69996003B2FB9 /* MFViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF16021E69996003B2FB9 /* MFViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF17421E69E1F003B2FB9 /* MFCustomButton.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF16A21E69E1F003B2FB9 /* MFCustomButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF17521E69E1F003B2FB9 /* ButtonDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF16B21E69E1F003B2FB9 /* ButtonDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF17621E69E1F003B2FB9 /* PrimaryButton.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF16C21E69E1F003B2FB9 /* PrimaryButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF17721E69E1F003B2FB9 /* MFTextButton.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF16D21E69E1F003B2FB9 /* MFTextButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF17021E69E1F003B2FB9 /* MFCustomButton.m */; }; - D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF17121E69E1F003B2FB9 /* PrimaryButton.m */; }; - D29DF17C21E69E1F003B2FB9 /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF17221E69E1F003B2FB9 /* MFTextButton.m */; }; - D29DF18021E69E49003B2FB9 /* MFView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF17E21E69E2E003B2FB9 /* MFView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF18121E69E50003B2FB9 /* MFView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF17F21E69E2E003B2FB9 /* MFView.m */; }; - D29DF18221E69E54003B2FB9 /* SeparatorView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF15921E697DA003B2FB9 /* SeparatorView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF15A21E697DA003B2FB9 /* SeparatorView.m */; }; - D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF24221E6A176003B2FB9 /* MFTextField.m */; }; - D29DF24E21E6A177003B2FB9 /* MFDigitTextField.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF24321E6A176003B2FB9 /* MFDigitTextField.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF24F21E6A177003B2FB9 /* MFTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = D29DF24421E6A176003B2FB9 /* MFTextField.xib */; }; - D29DF25021E6A177003B2FB9 /* MFDigitTextBox.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF24521E6A176003B2FB9 /* MFDigitTextBox.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF25121E6A177003B2FB9 /* MFDigitTextBox.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF24621E6A176003B2FB9 /* MFDigitTextBox.m */; }; - D29DF25221E6A177003B2FB9 /* MFMdnTextField.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF24721E6A176003B2FB9 /* MFMdnTextField.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF24821E6A177003B2FB9 /* MFDigitTextField.m */; }; - D29DF25421E6A177003B2FB9 /* MFMdnTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF24921E6A177003B2FB9 /* MFMdnTextField.m */; }; - D29DF25521E6A177003B2FB9 /* MFDigitTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = D29DF24A21E6A177003B2FB9 /* MFDigitTextField.xib */; }; - D29DF25621E6A177003B2FB9 /* MFTextFieldSubclassExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF24B21E6A177003B2FB9 /* MFTextFieldSubclassExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF25721E6A177003B2FB9 /* MFTextField.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF24C21E6A177003B2FB9 /* MFTextField.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF25921E6A22D003B2FB9 /* MFButtonProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF26821E6AA0B003B2FB9 /* FLAnimatedImage.m */; }; - D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF26921E6AA0B003B2FB9 /* FLAnimatedImageView.m */; }; - D29DF26E21E6AA0B003B2FB9 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF26A21E6AA0B003B2FB9 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF26F21E6AA0B003B2FB9 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF26B21E6AA0B003B2FB9 /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF27521E79E81003B2FB9 /* MVMCoreUILoggingHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF27321E79E81003B2FB9 /* MVMCoreUILoggingHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */; }; - D29DF27921E7A533003B2FB9 /* MVMCoreUISession.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF27721E7A533003B2FB9 /* MVMCoreUISession.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF27821E7A533003B2FB9 /* MVMCoreUISession.m */; }; - D29DF28021E7AA51003B2FB9 /* MVMCoreUIDetailViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF27F21E7AA50003B2FB9 /* MVMCoreUIDetailViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28121E7AB23003B2FB9 /* MVMCoreUICommonViewsUtility.m */; }; - D29DF28421E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF28221E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF28B21E7AC2B003B2FB9 /* ViewConstrainingView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */; }; - D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28D21E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m */; }; - D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28E21E7ADB8003B2FB9 /* StackableViewController.m */; }; - D29DF29721E7ADB8003B2FB9 /* MFScrollingViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */; }; - D29DF29921E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF29A21E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF29B21E7ADB9003B2FB9 /* StackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29321E7ADB8003B2FB9 /* StackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */; }; - D29DF29D21E7AE38003B2FB9 /* MFStyler.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF13821E68636003B2FB9 /* MFStyler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF13921E68637003B2FB9 /* MFStyler.m */; }; - D29DF2A121E7AF4E003B2FB9 /* MVMCoreUIUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29F21E7AF4E003B2FB9 /* MVMCoreUIUtility.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2A021E7AF4E003B2FB9 /* MVMCoreUIUtility.m */; }; - D29DF2A921E7B2F9003B2FB9 /* MVMCoreUIConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2A721E7B2F9003B2FB9 /* MVMCoreUIConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2A821E7B2F9003B2FB9 /* MVMCoreUIConstants.m */; }; - D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2AB21E7B3A4003B2FB9 /* MFTextView.m */; }; - D29DF2AF21E7B3A4003B2FB9 /* MFTextView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D29DF2AC21E7B3A4003B2FB9 /* MFTextView.xib */; }; - D29DF2B021E7B3A4003B2FB9 /* MFTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2AD21E7B3A4003B2FB9 /* MFTextView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2B321E7B76D003B2FB9 /* MFLoadingSpinner.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2B121E7B76C003B2FB9 /* MFLoadingSpinner.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2B221E7B76D003B2FB9 /* MFLoadingSpinner.m */; }; - D29DF2BC21E7BEA4003B2FB9 /* TopTabbar.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2B821E7BEA4003B2FB9 /* TopTabbar.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2BD21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2B921E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2BA21E7BEA4003B2FB9 /* TopTabbar.m */; }; - D29DF2BF21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2BB21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m */; }; - D29DF2C421E7BF57003B2FB9 /* MFTabBarSwipeAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2C021E7BF56003B2FB9 /* MFTabBarSwipeAnimator.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2C121E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m */; }; - D29DF2C621E7BF57003B2FB9 /* MFTabBarInteractor.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2C221E7BF57003B2FB9 /* MFTabBarInteractor.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2C321E7BF57003B2FB9 /* MFTabBarInteractor.m */; }; - D29DF2C821E7BFC1003B2FB9 /* MFSizeObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF14521E68728003B2FB9 /* MFSizeObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF14421E68728003B2FB9 /* MFSizeObject.m */; }; - D29DF2CA21E7BFC8003B2FB9 /* MFSizeThreshold.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF14621E68728003B2FB9 /* MFSizeThreshold.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF14721E68728003B2FB9 /* MFSizeThreshold.m */; }; - D29DF2CE21E7C104003B2FB9 /* MFLoadingViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */; }; - D29DF2E121E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2E021E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2EE21ECEADF003B2FB9 /* MFFonts.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF14D21E693AD003B2FB9 /* MFFonts.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF14C21E693AD003B2FB9 /* MFFonts.m */; }; - D29DF31A21ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31621ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf */; }; - D29DF31B21ECECC0003B2FB9 /* OCRAExtended.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */; }; - D29DF31C21ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31821ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf */; }; - D29DF31D21ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31921ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf */; }; - D29DF32021ED0CBA003B2FB9 /* LabelView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF31E21ED0CBA003B2FB9 /* LabelView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF31F21ED0CBA003B2FB9 /* LabelView.m */; }; - D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF32221ED0DA2003B2FB9 /* TextButtonView.m */; }; - D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF32321ED0DA2003B2FB9 /* TextButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32821EE8736003B2FB9 /* Localizable.strings */; }; - D29DF32E21EE8C3D003B2FB9 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */; }; - D2A514582211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */; }; - D2A5145D2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */; }; - D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */; }; - D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */; }; - D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* StandardHeaderView.swift */; }; - D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; }; - D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A638FC22CA98280052ED1F /* HeadlineBody.swift */; }; - D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390022CBB1820052ED1F /* Carousel.swift */; }; - D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */; }; - D2B18B7F2360913400A9AEDC /* Control.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B7E2360913400A9AEDC /* Control.swift */; }; - D2B18B812360945C00A9AEDC /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B802360945C00A9AEDC /* View.swift */; }; - D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */; }; - D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B93236214AD00A9AEDC /* NavigationController.swift */; }; - D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */; }; - D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; }; - D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; }; - D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; }; - D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; }; - D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; }; - D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; }; - D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */; }; - D2FB151D23A40F1500C20E10 /* StackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151C23A40F1500C20E10 /* StackItem.swift */; }; - DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; }; - DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; }; - DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; }; - DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391A224421A0001AB423 /* CaretButton.swift */; }; - DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */; }; - DBEFFA04225A829700230692 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB891E822253FA8500022516 /* Label.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 01004F2F22721C3800991ECC /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = ""; }; - 0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = ""; }; - 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = ""; }; - 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = ""; }; - 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = ""; }; - 012A88ED239858E300FE3DA1 /* ContainerMoleculeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerMoleculeProtocol.swift; sourceTree = ""; }; - 012CA98823849699003F810F /* SeperatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeperatorModel.swift; sourceTree = ""; }; - 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFTextField+ModelExtension.swift"; sourceTree = ""; }; - 012CA99B23859FDC003F810F /* ViewConstrainingView+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ViewConstrainingView+ModelExtension.swift"; sourceTree = ""; }; - 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFView+ModelExtension.swift"; sourceTree = ""; }; - 012CA9BD2385C692003F810F /* ConstrainingMoleculeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstrainingMoleculeProtocol.swift; sourceTree = ""; }; - 01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeTableViewCell.swift; sourceTree = ""; }; - 01509D902327ECE600EF99AA /* CornerLabels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CornerLabels.swift; sourceTree = ""; }; - 01509D922327ECFB00EF99AA /* ProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = ""; }; - 01509D942327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyTextButtonSwitch.swift; sourceTree = ""; }; - 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonLabel.swift; sourceTree = ""; }; - 017BEB392360EEB40024EF95 /* PageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageModel.swift; sourceTree = ""; }; - 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFViewController+Model.swift"; sourceTree = ""; }; - 017BEB3F23620A230024EF95 /* TextFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldModel.swift; sourceTree = ""; }; - 017BEB4123620AD20024EF95 /* FormModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormModelProtocol.swift; sourceTree = ""; }; - 017BEB432362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIMoleculeMappingObject+ModelExtension.swift"; sourceTree = ""; }; - 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeViewProtocol.swift; sourceTree = ""; }; - 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelMoleculeViewProtocol.swift; sourceTree = ""; }; - 017BEB7A236763000024EF95 /* LineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineModel.swift; sourceTree = ""; }; - 017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeObjectMapping.swift; sourceTree = ""; }; - 0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; - 0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = ""; }; - 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; - 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = ""; }; - 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; - 01EB3683236097C0006832FA /* MoleculeProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeProtocol.swift; sourceTree = ""; }; - 01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = ""; }; - 01EB368923609801006832FA /* ListItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListItemModel.swift; sourceTree = ""; }; - 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackItemModel.swift; sourceTree = ""; }; - 01EB368B23609801006832FA /* MoleculeStackModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackModel.swift; sourceTree = ""; }; - 01EB368C23609801006832FA /* HeaderModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderModel.swift; sourceTree = ""; }; - 01EB368D23609801006832FA /* HeadlineBodyModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyModel.swift; sourceTree = ""; }; - 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; - 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackViewAlignment+Extension.swift"; sourceTree = ""; }; - 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = ""; }; - 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; - 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; - 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; - 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = ""; }; - 0AA33B35239813EE0067DD0F /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; - 943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = ""; }; - 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = ""; }; - 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBarModel.swift; sourceTree = ""; }; - 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgressModel.swift; sourceTree = ""; }; - 9445891E2385D2E900DE9FD4 /* CaretViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaretViewModel.swift; sourceTree = ""; }; - 944589202385D6E900DE9FD4 /* DashLineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashLineModel.swift; sourceTree = ""; }; - 944589222385DA9500DE9FD4 /* ImageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewModel.swift; sourceTree = ""; }; - 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; - 946EE1B9237B66D80036751F /* ModelHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelHelper.swift; sourceTree = ""; }; - 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; - 94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeModel.swift; sourceTree = ""; }; - 94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeUnderlineModel.swift; sourceTree = ""; }; - 94C2D9A223872C110006CF46 /* LabelAttributeStrikeThroughModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeStrikeThroughModel.swift; sourceTree = ""; }; - 94C2D9A423872C350006CF46 /* LabelAttributeFontModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeFontModel.swift; sourceTree = ""; }; - 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeColorModel.swift; sourceTree = ""; }; - 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeImageModel.swift; sourceTree = ""; }; - 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeActionModel.swift; sourceTree = ""; }; - D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; - D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; - D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = ""; }; - D22479892314445E003FCCF9 /* LabelSwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelSwitch.swift; sourceTree = ""; }; - D224798B231450C8003FCCF9 /* HeadlineBodySwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodySwitch.swift; sourceTree = ""; }; - D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSLayoutConstraintExtension.swift; sourceTree = ""; }; - D22479952316AF6D003FCCF9 /* HeadlineBodyTextButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyTextButton.swift; sourceTree = ""; }; - D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionMoleculeTableViewCell.swift; sourceTree = ""; }; - D22D1F18220341F50077CEC0 /* MVMCoreUICheckBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUICheckBox.h; sourceTree = ""; }; - D22D1F19220341F50077CEC0 /* MVMCoreUICheckBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUICheckBox.m; sourceTree = ""; }; - D22D1F1C220343560077CEC0 /* MVMCoreUICheckMarkView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUICheckMarkView.h; sourceTree = ""; }; - D22D1F1D220343560077CEC0 /* MVMCoreUICheckMarkView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUICheckMarkView.m; sourceTree = ""; }; - D22D1F44220496A30077CEC0 /* MVMCoreUISwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUISwitch.h; sourceTree = ""; }; - D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISwitch.m; sourceTree = ""; }; - D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIStackableViewController.h; sourceTree = ""; }; - D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIStackableViewController.m; sourceTree = ""; }; - D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; - D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPageControl.h; sourceTree = ""; }; - D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIPageControl.m; sourceTree = ""; }; - D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = ""; }; - D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = ""; }; - D268C711238D6699007F2C1C /* DropDown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDown.swift; sourceTree = ""; }; - D274CA322236A78900B01B62 /* StandardFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardFooterView.swift; sourceTree = ""; }; - D2755D7A23689C7500485468 /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = ""; }; - D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewCell.swift; sourceTree = ""; }; - D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EyebrowHeadlineBodyLink.swift; sourceTree = ""; }; - D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFLoadImageView.swift; sourceTree = ""; }; - D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFTransparentGIFView.swift; sourceTree = ""; }; - D282AACA2243C61700C46919 /* ButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonView.swift; sourceTree = ""; }; - D296E13B2295969C0051EBE7 /* MoleculeListCellProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoleculeListCellProtocol.h; sourceTree = ""; }; - D296E1402295EBBA0051EBE7 /* MoleculeDelegateProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoleculeDelegateProtocol.h; sourceTree = ""; }; - D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewConstrainingProtocol.h; sourceTree = ""; }; - D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsView.m; sourceTree = ""; }; - D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLabelsView.h; sourceTree = ""; }; - D29770EE21F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsAndBottomButtonsTableViewController.m; sourceTree = ""; }; - D29770EF21F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLabelsAndBottomButtonsTableViewController.h; sourceTree = ""; }; - D29770F021F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLabelsAndBottomButtonsViewController.h; sourceTree = ""; }; - D29770F121F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsAndBottomButtonsViewController.m; sourceTree = ""; }; - D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITextFieldView.m; sourceTree = ""; }; - D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITextFieldView.h; sourceTree = ""; }; - D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModuleMolecule.swift; sourceTree = ""; }; - D29DF0CC21E404D4003B2FB9 /* MVMCoreUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MVMCoreUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUI.h; sourceTree = ""; }; - D29DF0D021E404D4003B2FB9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MVMCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+MFConvenience.h"; sourceTree = ""; }; - D29DF11221E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSLayoutConstraint+MFConvenience.h"; sourceTree = ""; }; - D29DF11321E6805F003B2FB9 /* UIColor+MFConvenience.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+MFConvenience.m"; sourceTree = ""; }; - D29DF11421E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSLayoutConstraint+MFConvenience.m"; sourceTree = ""; }; - D29DF11A21E684A9003B2FB9 /* MVMCoreUISplitViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUISplitViewController.h; sourceTree = ""; }; - D29DF11B21E684A9003B2FB9 /* MVMCoreUISplitViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISplitViewController.m; sourceTree = ""; }; - D29DF11F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertMainView.h; sourceTree = ""; }; - D29DF12021E6851E003B2FB9 /* MVMCoreUITopAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertView.h; sourceTree = ""; }; - D29DF12121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertExpandableView.m; sourceTree = ""; }; - D29DF12221E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertShortView.h; sourceTree = ""; }; - D29DF12321E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertBaseView.h; sourceTree = ""; }; - D29DF12421E6851E003B2FB9 /* MVMCoreUITopAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertView.m; sourceTree = ""; }; - D29DF12521E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertMainView.m; sourceTree = ""; }; - D29DF12621E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertShortView.m; sourceTree = ""; }; - D29DF12721E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertExpandableView.h; sourceTree = ""; }; - D29DF12821E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertBaseView.m; sourceTree = ""; }; - D29DF13821E68636003B2FB9 /* MFStyler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFStyler.h; sourceTree = ""; }; - D29DF13921E68637003B2FB9 /* MFStyler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFStyler.m; sourceTree = ""; }; - D29DF14421E68728003B2FB9 /* MFSizeObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFSizeObject.m; sourceTree = ""; }; - D29DF14521E68728003B2FB9 /* MFSizeObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFSizeObject.h; sourceTree = ""; }; - D29DF14621E68728003B2FB9 /* MFSizeThreshold.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFSizeThreshold.h; sourceTree = ""; }; - D29DF14721E68728003B2FB9 /* MFSizeThreshold.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFSizeThreshold.m; sourceTree = ""; }; - D29DF14C21E693AD003B2FB9 /* MFFonts.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFFonts.m; sourceTree = ""; }; - D29DF14D21E693AD003B2FB9 /* MFFonts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFFonts.h; sourceTree = ""; }; - D29DF15321E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPanelButtonProtocol.h; sourceTree = ""; }; - D29DF15921E697DA003B2FB9 /* SeparatorView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SeparatorView.h; sourceTree = ""; }; - D29DF15A21E697DA003B2FB9 /* SeparatorView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SeparatorView.m; sourceTree = ""; }; - D29DF15F21E69996003B2FB9 /* MFViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFViewController.m; sourceTree = ""; }; - D29DF16021E69996003B2FB9 /* MFViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFViewController.h; sourceTree = ""; }; - D29DF16A21E69E1F003B2FB9 /* MFCustomButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFCustomButton.h; sourceTree = ""; }; - D29DF16B21E69E1F003B2FB9 /* ButtonDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ButtonDelegateProtocol.h; sourceTree = ""; }; - D29DF16C21E69E1F003B2FB9 /* PrimaryButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrimaryButton.h; sourceTree = ""; }; - D29DF16D21E69E1F003B2FB9 /* MFTextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextButton.h; sourceTree = ""; }; - D29DF17021E69E1F003B2FB9 /* MFCustomButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFCustomButton.m; sourceTree = ""; }; - D29DF17121E69E1F003B2FB9 /* PrimaryButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PrimaryButton.m; sourceTree = ""; }; - D29DF17221E69E1F003B2FB9 /* MFTextButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextButton.m; sourceTree = ""; }; - D29DF17E21E69E2E003B2FB9 /* MFView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFView.h; sourceTree = ""; }; - D29DF17F21E69E2E003B2FB9 /* MFView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFView.m; sourceTree = ""; }; - D29DF24221E6A176003B2FB9 /* MFTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextField.m; sourceTree = ""; }; - D29DF24321E6A176003B2FB9 /* MFDigitTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFDigitTextField.h; sourceTree = ""; }; - D29DF24421E6A176003B2FB9 /* MFTextField.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MFTextField.xib; sourceTree = ""; }; - D29DF24521E6A176003B2FB9 /* MFDigitTextBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFDigitTextBox.h; sourceTree = ""; }; - D29DF24621E6A176003B2FB9 /* MFDigitTextBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFDigitTextBox.m; sourceTree = ""; }; - D29DF24721E6A176003B2FB9 /* MFMdnTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFMdnTextField.h; sourceTree = ""; }; - D29DF24821E6A177003B2FB9 /* MFDigitTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFDigitTextField.m; sourceTree = ""; }; - D29DF24921E6A177003B2FB9 /* MFMdnTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFMdnTextField.m; sourceTree = ""; }; - D29DF24A21E6A177003B2FB9 /* MFDigitTextField.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MFDigitTextField.xib; sourceTree = ""; }; - D29DF24B21E6A177003B2FB9 /* MFTextFieldSubclassExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextFieldSubclassExtension.h; sourceTree = ""; }; - D29DF24C21E6A177003B2FB9 /* MFTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextField.h; sourceTree = ""; }; - D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFButtonProtocol.h; sourceTree = ""; }; - D29DF26821E6AA0B003B2FB9 /* FLAnimatedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImage.m; sourceTree = ""; }; - D29DF26921E6AA0B003B2FB9 /* FLAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImageView.m; sourceTree = ""; }; - D29DF26A21E6AA0B003B2FB9 /* FLAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImage.h; sourceTree = ""; }; - D29DF26B21E6AA0B003B2FB9 /* FLAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImageView.h; sourceTree = ""; }; - D29DF27321E79E81003B2FB9 /* MVMCoreUILoggingHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUILoggingHandler.h; sourceTree = ""; }; - D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUILoggingHandler.m; sourceTree = ""; }; - D29DF27721E7A533003B2FB9 /* MVMCoreUISession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUISession.h; sourceTree = ""; }; - D29DF27821E7A533003B2FB9 /* MVMCoreUISession.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISession.m; sourceTree = ""; }; - D29DF27F21E7AA50003B2FB9 /* MVMCoreUIDetailViewProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIDetailViewProtocol.h; sourceTree = ""; }; - D29DF28121E7AB23003B2FB9 /* MVMCoreUICommonViewsUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUICommonViewsUtility.m; sourceTree = ""; }; - D29DF28221E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUICommonViewsUtility.h; sourceTree = ""; }; - D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewConstrainingView.h; sourceTree = ""; }; - D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewConstrainingView.m; sourceTree = ""; }; - D29DF28D21E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgrammaticScrollViewController.m; sourceTree = ""; }; - D29DF28E21E7ADB8003B2FB9 /* StackableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StackableViewController.m; sourceTree = ""; }; - D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFScrollingViewController.h; sourceTree = ""; }; - D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFScrollingViewController.m; sourceTree = ""; }; - D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgrammaticScrollViewController.h; sourceTree = ""; }; - D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFProgrammaticTableViewController.h; sourceTree = ""; }; - D29DF29321E7ADB8003B2FB9 /* StackableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackableViewController.h; sourceTree = ""; }; - D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFProgrammaticTableViewController.m; sourceTree = ""; }; - D29DF29F21E7AF4E003B2FB9 /* MVMCoreUIUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIUtility.h; sourceTree = ""; }; - D29DF2A021E7AF4E003B2FB9 /* MVMCoreUIUtility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIUtility.m; sourceTree = ""; }; - D29DF2A721E7B2F9003B2FB9 /* MVMCoreUIConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIConstants.h; sourceTree = ""; }; - D29DF2A821E7B2F9003B2FB9 /* MVMCoreUIConstants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIConstants.m; sourceTree = ""; }; - D29DF2AB21E7B3A4003B2FB9 /* MFTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextView.m; sourceTree = ""; }; - D29DF2AC21E7B3A4003B2FB9 /* MFTextView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MFTextView.xib; sourceTree = ""; }; - D29DF2AD21E7B3A4003B2FB9 /* MFTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextView.h; sourceTree = ""; }; - D29DF2B121E7B76C003B2FB9 /* MFLoadingSpinner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFLoadingSpinner.h; sourceTree = ""; }; - D29DF2B221E7B76D003B2FB9 /* MFLoadingSpinner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFLoadingSpinner.m; sourceTree = ""; }; - D29DF2B821E7BEA4003B2FB9 /* TopTabbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopTabbar.h; sourceTree = ""; }; - D29DF2B921E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITabBarPageControlViewController.h; sourceTree = ""; }; - D29DF2BA21E7BEA4003B2FB9 /* TopTabbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopTabbar.m; sourceTree = ""; }; - D29DF2BB21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITabBarPageControlViewController.m; sourceTree = ""; }; - D29DF2C021E7BF56003B2FB9 /* MFTabBarSwipeAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTabBarSwipeAnimator.h; sourceTree = ""; }; - D29DF2C121E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTabBarSwipeAnimator.m; sourceTree = ""; }; - D29DF2C221E7BF57003B2FB9 /* MFTabBarInteractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTabBarInteractor.h; sourceTree = ""; }; - D29DF2C321E7BF57003B2FB9 /* MFTabBarInteractor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTabBarInteractor.m; sourceTree = ""; }; - D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFLoadingViewController.h; sourceTree = ""; }; - D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFLoadingViewController.m; sourceTree = ""; }; - D29DF2E021E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPanelProtocol.h; sourceTree = ""; }; - D29DF31621ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-45Lt.otf"; sourceTree = ""; }; - D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = OCRAExtended.ttf; sourceTree = ""; }; - D29DF31821ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-75Bd.otf"; sourceTree = ""; }; - D29DF31921ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-55Rg.otf"; sourceTree = ""; }; - D29DF31E21ED0CBA003B2FB9 /* LabelView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelView.h; sourceTree = ""; }; - D29DF31F21ED0CBA003B2FB9 /* LabelView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LabelView.m; sourceTree = ""; }; - D29DF32221ED0DA2003B2FB9 /* TextButtonView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextButtonView.m; sourceTree = ""; }; - D29DF32321ED0DA2003B2FB9 /* TextButtonView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextButtonView.h; sourceTree = ""; }; - D29DF32921EE8736003B2FB9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - D29DF32A21EE8736003B2FB9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; - D29DF32B21EE8736003B2FB9 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = ""; }; - D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; - D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIMoleculeMappingObject.h; sourceTree = ""; }; - D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIMoleculeMappingObject.m; sourceTree = ""; }; - D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIMoleculeViewProtocol.h; sourceTree = ""; }; - D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = ""; }; - D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackTemplate.swift; sourceTree = ""; }; - D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackCenteredTemplate.swift; sourceTree = ""; }; - D2A514662213885800345BFB /* StandardHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardHeaderView.swift; sourceTree = ""; }; - D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerViewController.swift; sourceTree = ""; }; - D2A638FC22CA98280052ED1F /* HeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBody.swift; sourceTree = ""; }; - D2A6390022CBB1820052ED1F /* Carousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Carousel.swift; sourceTree = ""; }; - D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeCollectionViewCell.swift; sourceTree = ""; }; - D2B18B7E2360913400A9AEDC /* Control.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Control.swift; sourceTree = ""; }; - D2B18B802360945C00A9AEDC /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = ""; }; - D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreUIObject.swift; sourceTree = ""; }; - D2B18B93236214AD00A9AEDC /* NavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = ""; }; - D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageHeadlineBody.swift; sourceTree = ""; }; - D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = ""; }; - D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = ""; }; - D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = ""; }; - D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = ""; }; - D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = ""; }; - D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = ""; }; - D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = ""; }; - D2F4DDE52371A4CB00CD28BB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainer.swift; sourceTree = ""; }; - D2FB151C23A40F1500C20E10 /* StackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackItem.swift; sourceTree = ""; }; - DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeftRightLabelView.swift; sourceTree = ""; }; - DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; - DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = ""; }; - DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = ""; }; - DBC4391A224421A0001AB423 /* CaretButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretButton.swift; sourceTree = ""; }; - DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelWithInternalButton.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - D29DF0C921E404D4003B2FB9 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */, - 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 01509D96232803B200EF99AA /* Models */ = { - isa = PBXGroup; - children = ( - 0AA33B322398134B0067DD0F /* Primitive Models */, - 017BEB392360EEB40024EF95 /* PageModel.swift */, - 01EB3683236097C0006832FA /* MoleculeProtocol.swift */, - 012A88ED239858E300FE3DA1 /* ContainerMoleculeProtocol.swift */, - 012CA9BD2385C692003F810F /* ConstrainingMoleculeProtocol.swift */, - 946EE1B5237B663A0036751F /* Extensions */, - 01EB368723609801006832FA /* Molecules */, - ); - path = Models; - sourceTree = ""; - }; - 01C74D87224298E2009C25A3 /* FormUIHelpers */ = { - isa = PBXGroup; - children = ( - 0198F79E225679870066C936 /* FormValidationProtocol.swift */, - 0105618A224BBE7700E1557D /* FormValidator.swift */, - 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */, - 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */, - ); - path = FormUIHelpers; - sourceTree = ""; - }; - 01EB368723609801006832FA /* Molecules */ = { - isa = PBXGroup; - children = ( - 012CA98823849699003F810F /* SeperatorModel.swift */, - 01EB368923609801006832FA /* ListItemModel.swift */, - 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */, - 01EB368B23609801006832FA /* MoleculeStackModel.swift */, - 01EB368C23609801006832FA /* HeaderModel.swift */, - 01EB368D23609801006832FA /* HeadlineBodyModel.swift */, - 017BEB3F23620A230024EF95 /* TextFieldModel.swift */, - 017BEB4123620AD20024EF95 /* FormModelProtocol.swift */, - 017BEB7A236763000024EF95 /* LineModel.swift */, - ); - path = Molecules; - sourceTree = ""; - }; - 0AA33B322398134B0067DD0F /* Primitive Models */ = { - isa = PBXGroup; - children = ( - 0AA33B35239813EE0067DD0F /* Color.swift */, - ); - path = "Primitive Models"; - sourceTree = ""; - }; - 946EE1B5237B663A0036751F /* Extensions */ = { - isa = PBXGroup; - children = ( - 946EE1B9237B66D80036751F /* ModelHelper.swift */, - ); - path = Extensions; - sourceTree = ""; - }; - 94C2D9822386F3E30006CF46 /* LabelModel */ = { - isa = PBXGroup; - children = ( - 01EB368823609801006832FA /* LabelModel.swift */, - 94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */, - 94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */, - 94C2D9A223872C110006CF46 /* LabelAttributeStrikeThroughModel.swift */, - 94C2D9A423872C350006CF46 /* LabelAttributeFontModel.swift */, - 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */, - 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */, - 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */, - ); - path = LabelModel; - sourceTree = ""; - }; - 94FB5B83238D892800EB2193 /* Recovered References */ = { - isa = PBXGroup; - children = ( - ); - name = "Recovered References"; - sourceTree = ""; - }; - D213347423842FE3008E41B3 /* Controllers */ = { - isa = PBXGroup; - children = ( - D29DF29321E7ADB8003B2FB9 /* StackableViewController.h */, - D29DF28E21E7ADB8003B2FB9 /* StackableViewController.m */, - D29770F021F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h */, - D29770F121F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m */, - D29770EF21F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h */, - D29770EE21F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m */, - ); - path = Controllers; - sourceTree = ""; - }; - D213347523842FF5008E41B3 /* Views */ = { - isa = PBXGroup; - children = ( - D29DF17E21E69E2E003B2FB9 /* MFView.h */, - D29DF17F21E69E2E003B2FB9 /* MFView.m */, - D29DF31E21ED0CBA003B2FB9 /* LabelView.h */, - D29DF31F21ED0CBA003B2FB9 /* LabelView.m */, - D29DF15921E697DA003B2FB9 /* SeparatorView.h */, - D29DF15A21E697DA003B2FB9 /* SeparatorView.m */, - D22D1F1C220343560077CEC0 /* MVMCoreUICheckMarkView.h */, - D22D1F1D220343560077CEC0 /* MVMCoreUICheckMarkView.m */, - D22D1F18220341F50077CEC0 /* MVMCoreUICheckBox.h */, - D22D1F19220341F50077CEC0 /* MVMCoreUICheckBox.m */, - 0198F7A02256A80A0066C936 /* MFRadioButton.h */, - 0198F7A22256A80A0066C936 /* MFRadioButton.m */, - ); - path = Views; - sourceTree = ""; - }; - D224798823142BF2003FCCF9 /* SwitchMolecules */ = { - isa = PBXGroup; - children = ( - 01509D942327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift */, - D22479892314445E003FCCF9 /* LabelSwitch.swift */, - D224798B231450C8003FCCF9 /* HeadlineBodySwitch.swift */, - ); - path = SwitchMolecules; - sourceTree = ""; - }; - D224798D2316A988003FCCF9 /* VerticalCombinationViews */ = { - isa = PBXGroup; - children = ( - D2A638FC22CA98280052ED1F /* HeadlineBody.swift */, - D22479952316AF6D003FCCF9 /* HeadlineBodyTextButton.swift */, - D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */, - ); - path = VerticalCombinationViews; - sourceTree = ""; - }; - D224798E2316A995003FCCF9 /* HorizontalCombinationViews */ = { - isa = PBXGroup; - children = ( - D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */, - D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */, - ); - path = HorizontalCombinationViews; - sourceTree = ""; - }; - D224798F2316A99F003FCCF9 /* LeftRightViews */ = { - isa = PBXGroup; - children = ( - 01509D902327ECE600EF99AA /* CornerLabels.swift */, - D224798823142BF2003FCCF9 /* SwitchMolecules */, - ); - path = LeftRightViews; - sourceTree = ""; - }; - D22479902316A9CB003FCCF9 /* Organisms */ = { - isa = PBXGroup; - children = ( - D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */, - D2A6390022CBB1820052ED1F /* Carousel.swift */, - ); - path = Organisms; - sourceTree = ""; - }; - D22479912316A9EF003FCCF9 /* Items */ = { - isa = PBXGroup; - children = ( - D2755D7A23689C7500485468 /* TableViewCell.swift */, - 01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */, - D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */, - D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */, - D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */, - D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */, - D2FB151C23A40F1500C20E10 /* StackItem.swift */, - ); - path = Items; - sourceTree = ""; - }; - D22D1F582204D2590077CEC0 /* Legacy */ = { - isa = PBXGroup; - children = ( - D213347523842FF5008E41B3 /* Views */, - D213347423842FE3008E41B3 /* Controllers */, - ); - path = Legacy; - sourceTree = ""; - }; - D29DF0C221E404D4003B2FB9 = { - isa = PBXGroup; - children = ( - D29DF0CE21E404D4003B2FB9 /* MVMCoreUI */, - D29DF0CD21E404D4003B2FB9 /* Products */, - D29DF0E421E4F3C7003B2FB9 /* Frameworks */, - 94FB5B83238D892800EB2193 /* Recovered References */, - ); - sourceTree = ""; - }; - D29DF0CD21E404D4003B2FB9 /* Products */ = { - isa = PBXGroup; - children = ( - D29DF0CC21E404D4003B2FB9 /* MVMCoreUI.framework */, - ); - name = Products; - sourceTree = ""; - }; - D29DF0CE21E404D4003B2FB9 /* MVMCoreUI */ = { - isa = PBXGroup; - children = ( - D29DF10D21E67A70003B2FB9 /* Atoms */, - 01509D96232803B200EF99AA /* Models */, - D2B18B7D236090D500A9AEDC /* BaseClasses */, - 01C74D87224298E2009C25A3 /* FormUIHelpers */, - D29DF31421ECECA7003B2FB9 /* SupportingFiles */, - D29DF27021E79B2C003B2FB9 /* OtherHandlers */, - D29DF13A21E68682003B2FB9 /* Utility */, - D29DF13321E68604003B2FB9 /* Styles */, - D29DF11021E6805F003B2FB9 /* Categories */, - D29DF11921E68467003B2FB9 /* Containers */, - D22D1F582204D2590077CEC0 /* Legacy */, - D29DF10F21E67A7D003B2FB9 /* BaseControllers */, - D29DF11E21E6851E003B2FB9 /* TopAlert */, - D29DF10E21E67A77003B2FB9 /* Molecules */, - D22479902316A9CB003FCCF9 /* Organisms */, - D29DF0DF21E418B2003B2FB9 /* Templates */, - D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */, - D29DF0D021E404D4003B2FB9 /* Info.plist */, - ); - path = MVMCoreUI; - sourceTree = ""; - }; - D29DF0DF21E418B2003B2FB9 /* Templates */ = { - isa = PBXGroup; - children = ( - 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */, - D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */, - D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */, - D296E13B2295969C0051EBE7 /* MoleculeListCellProtocol.h */, - D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */, - D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */, - ); - path = Templates; - sourceTree = ""; - }; - D29DF0E421E4F3C7003B2FB9 /* Frameworks */ = { - isa = PBXGroup; - children = ( - D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */, - 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - D29DF10D21E67A70003B2FB9 /* Atoms */ = { - isa = PBXGroup; - children = ( - D29DF22B21E6A0FA003B2FB9 /* TextFields */, - D29DF17D21E69E26003B2FB9 /* Views */, - D29DF16821E69E1F003B2FB9 /* Buttons */, - ); - path = Atoms; - sourceTree = ""; - }; - D29DF10E21E67A77003B2FB9 /* Molecules */ = { - isa = PBXGroup; - children = ( - D22479912316A9EF003FCCF9 /* Items */, - D224798F2316A99F003FCCF9 /* LeftRightViews */, - D224798E2316A995003FCCF9 /* HorizontalCombinationViews */, - D224798D2316A988003FCCF9 /* VerticalCombinationViews */, - D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */, - 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */, - 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */, - D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */, - D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */, - D2A514662213885800345BFB /* StandardHeaderView.swift */, - D274CA322236A78900B01B62 /* StandardFooterView.swift */, - 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */, - D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, - D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */, - 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */, - 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */, -<<<<<<< HEAD - 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */, - 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */, - D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, -======= - D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, - 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */, - 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */, ->>>>>>> e36d487d326f710d7302c6d9bcb758d209ad329c - ); - path = Molecules; - sourceTree = ""; - }; - D29DF10F21E67A7D003B2FB9 /* BaseControllers */ = { - isa = PBXGroup; - children = ( - D29DF16021E69996003B2FB9 /* MFViewController.h */, - D29DF15F21E69996003B2FB9 /* MFViewController.m */, - 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */, - D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */, - D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */, - D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */, - D29DF28D21E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m */, - D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */, - D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */, - D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */, - D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */, - D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */, - D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */, - D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */, - D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */, - D2F4DDE52371A4CB00CD28BB /* ViewController.swift */, - ); - path = BaseControllers; - sourceTree = ""; - }; - D29DF11021E6805F003B2FB9 /* Categories */ = { - isa = PBXGroup; - children = ( - D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */, - D29DF11321E6805F003B2FB9 /* UIColor+MFConvenience.m */, - D29DF11221E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h */, - D29DF11421E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m */, - D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */, - 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */, - ); - path = Categories; - sourceTree = ""; - }; - D29DF11921E68467003B2FB9 /* Containers */ = { - isa = PBXGroup; - children = ( - D29DF2B721E7BE79003B2FB9 /* TabBarController */, - D29DF2B621E7BE66003B2FB9 /* SplitViewController */, - D2B18B93236214AD00A9AEDC /* NavigationController.swift */, - D243859823A16B1800332775 /* Container.swift */, - ); - path = Containers; - sourceTree = ""; - }; - D29DF11E21E6851E003B2FB9 /* TopAlert */ = { - isa = PBXGroup; - children = ( - D29DF12021E6851E003B2FB9 /* MVMCoreUITopAlertView.h */, - D29DF12421E6851E003B2FB9 /* MVMCoreUITopAlertView.m */, - D29DF12321E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h */, - D29DF12821E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m */, - D29DF11F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h */, - D29DF12521E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m */, - D29DF12221E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h */, - D29DF12621E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m */, - D29DF12721E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h */, - D29DF12121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m */, - ); - path = TopAlert; - sourceTree = ""; - }; - D29DF13321E68604003B2FB9 /* Styles */ = { - isa = PBXGroup; - children = ( - D29DF13821E68636003B2FB9 /* MFStyler.h */, - D29DF13921E68637003B2FB9 /* MFStyler.m */, - ); - path = Styles; - sourceTree = ""; - }; - D29DF13A21E68682003B2FB9 /* Utility */ = { - isa = PBXGroup; - children = ( - D29DF13B21E6870B003B2FB9 /* Sizing */, - D29DF28221E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h */, - D29DF28121E7AB23003B2FB9 /* MVMCoreUICommonViewsUtility.m */, - D29DF14D21E693AD003B2FB9 /* MFFonts.h */, - D29DF14C21E693AD003B2FB9 /* MFFonts.m */, - D29DF29F21E7AF4E003B2FB9 /* MVMCoreUIUtility.h */, - D29DF2A021E7AF4E003B2FB9 /* MVMCoreUIUtility.m */, - D29DF2A721E7B2F9003B2FB9 /* MVMCoreUIConstants.h */, - D29DF2A821E7B2F9003B2FB9 /* MVMCoreUIConstants.m */, - 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */, - 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */, - D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */, - ); - path = Utility; - sourceTree = ""; - }; - D29DF13B21E6870B003B2FB9 /* Sizing */ = { - isa = PBXGroup; - children = ( - D29DF14521E68728003B2FB9 /* MFSizeObject.h */, - D29DF14421E68728003B2FB9 /* MFSizeObject.m */, - D29DF14621E68728003B2FB9 /* MFSizeThreshold.h */, - D29DF14721E68728003B2FB9 /* MFSizeThreshold.m */, - ); - path = Sizing; - sourceTree = ""; - }; - D29DF16821E69E1F003B2FB9 /* Buttons */ = { - isa = PBXGroup; - children = ( - DBC4391A224421A0001AB423 /* CaretButton.swift */, - D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */, - D29DF16B21E69E1F003B2FB9 /* ButtonDelegateProtocol.h */, - D29DF16A21E69E1F003B2FB9 /* MFCustomButton.h */, - D29DF17021E69E1F003B2FB9 /* MFCustomButton.m */, - D29DF16C21E69E1F003B2FB9 /* PrimaryButton.h */, - D29DF17121E69E1F003B2FB9 /* PrimaryButton.m */, - D282AACA2243C61700C46919 /* ButtonView.swift */, - D29DF16D21E69E1F003B2FB9 /* MFTextButton.h */, - D29DF17221E69E1F003B2FB9 /* MFTextButton.m */, - ); - path = Buttons; - sourceTree = ""; - }; - D29DF17D21E69E26003B2FB9 /* Views */ = { - isa = PBXGroup; - children = ( - 01509D922327ECFB00EF99AA /* ProgressBar.swift */, - 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */, - D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */, - D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */, - D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */, - 948DB67D2326DCD90011F916 /* MultiProgress.swift */, - 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */, - DBC4391622442196001AB423 /* CaretView.swift */, - 9445891E2385D2E900DE9FD4 /* CaretViewModel.swift */, - DBC4391722442197001AB423 /* DashLine.swift */, - 944589202385D6E900DE9FD4 /* DashLineModel.swift */, - DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */, - 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */, - D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */, - D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */, - 012CA99B23859FDC003F810F /* ViewConstrainingView+ModelExtension.swift */, - D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */, - D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */, - 944589222385DA9500DE9FD4 /* ImageViewModel.swift */, - D213347623843825008E41B3 /* Line.swift */, - D29DF2AD21E7B3A4003B2FB9 /* MFTextView.h */, - D29DF2AB21E7B3A4003B2FB9 /* MFTextView.m */, - D29DF2AC21E7B3A4003B2FB9 /* MFTextView.xib */, - D268C711238D6699007F2C1C /* DropDown.swift */, - D29DF2B121E7B76C003B2FB9 /* MFLoadingSpinner.h */, - D29DF2B221E7B76D003B2FB9 /* MFLoadingSpinner.m */, - D29DF32321ED0DA2003B2FB9 /* TextButtonView.h */, - D29DF32221ED0DA2003B2FB9 /* TextButtonView.m */, - D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */, - D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */, - D22D1F44220496A30077CEC0 /* MVMCoreUISwitch.h */, - D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */, - DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */, - DB891E822253FA8500022516 /* Label.swift */, - 94C2D9822386F3E30006CF46 /* LabelModel */, - 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, - 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */, - 01004F2F22721C3800991ECC /* RadioButton.swift */, - 943784F3236B77BB006A1E82 /* GraphView.swift */, - 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */, - ); - path = Views; - sourceTree = ""; - }; - D29DF22B21E6A0FA003B2FB9 /* TextFields */ = { - isa = PBXGroup; - children = ( - D29DF24C21E6A177003B2FB9 /* MFTextField.h */, - D29DF24221E6A176003B2FB9 /* MFTextField.m */, - 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */, - D29DF24421E6A176003B2FB9 /* MFTextField.xib */, - D29DF24B21E6A177003B2FB9 /* MFTextFieldSubclassExtension.h */, - D29DF24721E6A176003B2FB9 /* MFMdnTextField.h */, - D29DF24921E6A177003B2FB9 /* MFMdnTextField.m */, - D29DF24521E6A176003B2FB9 /* MFDigitTextBox.h */, - D29DF24621E6A176003B2FB9 /* MFDigitTextBox.m */, - D29DF24321E6A176003B2FB9 /* MFDigitTextField.h */, - D29DF24821E6A177003B2FB9 /* MFDigitTextField.m */, - D29DF24A21E6A177003B2FB9 /* MFDigitTextField.xib */, - ); - path = TextFields; - sourceTree = ""; - }; - D29DF26621E6A9E4003B2FB9 /* ThirdParty */ = { - isa = PBXGroup; - children = ( - D29DF26721E6AA0B003B2FB9 /* FLAnimatedImage */, - ); - path = ThirdParty; - sourceTree = ""; - }; - D29DF26721E6AA0B003B2FB9 /* FLAnimatedImage */ = { - isa = PBXGroup; - children = ( - D29DF26A21E6AA0B003B2FB9 /* FLAnimatedImage.h */, - D29DF26821E6AA0B003B2FB9 /* FLAnimatedImage.m */, - D29DF26B21E6AA0B003B2FB9 /* FLAnimatedImageView.h */, - D29DF26921E6AA0B003B2FB9 /* FLAnimatedImageView.m */, - ); - path = FLAnimatedImage; - sourceTree = ""; - }; - D29DF27021E79B2C003B2FB9 /* OtherHandlers */ = { - isa = PBXGroup; - children = ( - D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */, - D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */, - D29DF27721E7A533003B2FB9 /* MVMCoreUISession.h */, - D29DF27821E7A533003B2FB9 /* MVMCoreUISession.m */, - D29DF27321E79E81003B2FB9 /* MVMCoreUILoggingHandler.h */, - D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */, - D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */, - D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */, - D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */, - D296E1402295EBBA0051EBE7 /* MoleculeDelegateProtocol.h */, - D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */, - D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */, - 017BEB432362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift */, - 017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */, - ); - path = OtherHandlers; - sourceTree = ""; - }; - D29DF2B621E7BE66003B2FB9 /* SplitViewController */ = { - isa = PBXGroup; - children = ( - D29DF2E021E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h */, - D29DF27F21E7AA50003B2FB9 /* MVMCoreUIDetailViewProtocol.h */, - D29DF15321E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h */, - D29DF11A21E684A9003B2FB9 /* MVMCoreUISplitViewController.h */, - D29DF11B21E684A9003B2FB9 /* MVMCoreUISplitViewController.m */, - ); - path = SplitViewController; - sourceTree = ""; - }; - D29DF2B721E7BE79003B2FB9 /* TabBarController */ = { - isa = PBXGroup; - children = ( - D29DF2C021E7BF56003B2FB9 /* MFTabBarSwipeAnimator.h */, - D29DF2C121E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m */, - D29DF2C221E7BF57003B2FB9 /* MFTabBarInteractor.h */, - D29DF2C321E7BF57003B2FB9 /* MFTabBarInteractor.m */, - D29DF2B821E7BEA4003B2FB9 /* TopTabbar.h */, - D29DF2BA21E7BEA4003B2FB9 /* TopTabbar.m */, - D29DF2B921E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h */, - D29DF2BB21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m */, - ); - path = TabBarController; - sourceTree = ""; - }; - D29DF31421ECECA7003B2FB9 /* SupportingFiles */ = { - isa = PBXGroup; - children = ( - D29DF32721EE8736003B2FB9 /* Strings */, - D29DF26621E6A9E4003B2FB9 /* ThirdParty */, - D29DF31521ECECC0003B2FB9 /* Fonts */, - D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */, - ); - path = SupportingFiles; - sourceTree = ""; - }; - D29DF31521ECECC0003B2FB9 /* Fonts */ = { - isa = PBXGroup; - children = ( - D29DF31621ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf */, - D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */, - D29DF31821ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf */, - D29DF31921ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf */, - ); - path = Fonts; - sourceTree = ""; - }; - D29DF32721EE8736003B2FB9 /* Strings */ = { - isa = PBXGroup; - children = ( - D29DF32821EE8736003B2FB9 /* Localizable.strings */, - ); - path = Strings; - sourceTree = ""; - }; - D2B18B7D236090D500A9AEDC /* BaseClasses */ = { - isa = PBXGroup; - children = ( - D2B18B7E2360913400A9AEDC /* Control.swift */, - D2B18B802360945C00A9AEDC /* View.swift */, - ); - path = BaseClasses; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - D29DF0C721E404D4003B2FB9 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */, - D29DF18021E69E49003B2FB9 /* MFView.h in Headers */, - D29DF27921E7A533003B2FB9 /* MVMCoreUISession.h in Headers */, - D29DF29D21E7AE38003B2FB9 /* MFStyler.h in Headers */, - D29DF2B021E7B3A4003B2FB9 /* MFTextView.h in Headers */, - D29DF2A921E7B2F9003B2FB9 /* MVMCoreUIConstants.h in Headers */, - 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */, - D29DF25221E6A177003B2FB9 /* MFMdnTextField.h in Headers */, - D22D1F1A220341F60077CEC0 /* MVMCoreUICheckBox.h in Headers */, - D29DF29921E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h in Headers */, - D29DF11C21E684A9003B2FB9 /* MVMCoreUISplitViewController.h in Headers */, - D29DF29B21E7ADB9003B2FB9 /* StackableViewController.h in Headers */, - D29770F421F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h in Headers */, - D29DF15421E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h in Headers */, - D2A514582211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h in Headers */, - D29DF0D121E404D4003B2FB9 /* MVMCoreUI.h in Headers */, - D29DF29A21E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h in Headers */, - D29DF25621E6A177003B2FB9 /* MFTextFieldSubclassExtension.h in Headers */, - D29DF11521E6805F003B2FB9 /* UIColor+MFConvenience.h in Headers */, - D29DF2BC21E7BEA4003B2FB9 /* TopTabbar.h in Headers */, - D29DF25921E6A22D003B2FB9 /* MFButtonProtocol.h in Headers */, - D22D1F46220496A30077CEC0 /* MVMCoreUISwitch.h in Headers */, - D22D1F1E220343560077CEC0 /* MVMCoreUICheckMarkView.h in Headers */, - D29DF28421E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h in Headers */, - D22D1F562204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h in Headers */, - D29DF2CE21E7C104003B2FB9 /* MFLoadingViewController.h in Headers */, - D29DF12A21E6851E003B2FB9 /* MVMCoreUITopAlertView.h in Headers */, - D29DF27521E79E81003B2FB9 /* MVMCoreUILoggingHandler.h in Headers */, - D29DF28B21E7AC2B003B2FB9 /* ViewConstrainingView.h in Headers */, - D29DF2B321E7B76D003B2FB9 /* MFLoadingSpinner.h in Headers */, - D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */, - D29DF25021E6A177003B2FB9 /* MFDigitTextBox.h in Headers */, - D296E14722A5984C0051EBE7 /* MVMCoreUIViewConstrainingProtocol.h in Headers */, - D29DF2C621E7BF57003B2FB9 /* MFTabBarInteractor.h in Headers */, - D29DF25721E6A177003B2FB9 /* MFTextField.h in Headers */, - D29DF17521E69E1F003B2FB9 /* ButtonDelegateProtocol.h in Headers */, - D29DF18221E69E54003B2FB9 /* SeparatorView.h in Headers */, - D29DF26E21E6AA0B003B2FB9 /* FLAnimatedImage.h in Headers */, - D29DF11621E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h in Headers */, - D29DF17721E69E1F003B2FB9 /* MFTextButton.h in Headers */, - 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */, - D29DF16221E69996003B2FB9 /* MFViewController.h in Headers */, - D29DF13121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h in Headers */, - D29DF2C421E7BF57003B2FB9 /* MFTabBarSwipeAnimator.h in Headers */, - D2A5145D2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h in Headers */, - D29DF2CA21E7BFC8003B2FB9 /* MFSizeThreshold.h in Headers */, - D29DF28021E7AA51003B2FB9 /* MVMCoreUIDetailViewProtocol.h in Headers */, - D29DF2BD21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h in Headers */, - D29DF2EE21ECEADF003B2FB9 /* MFFonts.h in Headers */, - D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */, - D29DF24E21E6A177003B2FB9 /* MFDigitTextField.h in Headers */, - D29770F321F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h in Headers */, - D296E1412295EBBA0051EBE7 /* MoleculeDelegateProtocol.h in Headers */, - D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */, - D29770FD21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h in Headers */, - D29DF17421E69E1F003B2FB9 /* MFCustomButton.h in Headers */, - D29DF29721E7ADB8003B2FB9 /* MFScrollingViewController.h in Headers */, - D260D7B122D65BDD007E7233 /* MVMCoreUIPageControl.h in Headers */, - D29DF26F21E6AA0B003B2FB9 /* FLAnimatedImageView.h in Headers */, - D29DF2A121E7AF4E003B2FB9 /* MVMCoreUIUtility.h in Headers */, - D29DF17621E69E1F003B2FB9 /* PrimaryButton.h in Headers */, - D29DF2C821E7BFC1003B2FB9 /* MFSizeObject.h in Headers */, - D296E13C229598BF0051EBE7 /* MoleculeListCellProtocol.h in Headers */, - D29DF32021ED0CBA003B2FB9 /* LabelView.h in Headers */, - D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */, - D29DF2E121E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h in Headers */, - D29DF12921E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h in Headers */, - D29DF12C21E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - D29DF0CB21E404D4003B2FB9 /* MVMCoreUI */ = { - isa = PBXNativeTarget; - buildConfigurationList = D29DF0D421E404D4003B2FB9 /* Build configuration list for PBXNativeTarget "MVMCoreUI" */; - buildPhases = ( - D29DF0C721E404D4003B2FB9 /* Headers */, - D29DF0C821E404D4003B2FB9 /* Sources */, - D29DF0C921E404D4003B2FB9 /* Frameworks */, - D29DF0CA21E404D4003B2FB9 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = MVMCoreUI; - productName = MVMCoreUI; - productReference = D29DF0CC21E404D4003B2FB9 /* MVMCoreUI.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - D29DF0C321E404D4003B2FB9 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1010; - ORGANIZATIONNAME = "Verizon Wireless"; - TargetAttributes = { - D29DF0CB21E404D4003B2FB9 = { - CreatedOnToolsVersion = 10.1; - LastSwiftMigration = 1010; - ProvisioningStyle = Automatic; - }; - }; - }; - buildConfigurationList = D29DF0C621E404D4003B2FB9 /* Build configuration list for PBXProject "MVMCoreUI" */; - compatibilityVersion = "Xcode 8.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - es, - "es-MX", - ); - mainGroup = D29DF0C221E404D4003B2FB9; - productRefGroup = D29DF0CD21E404D4003B2FB9 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - D29DF0CB21E404D4003B2FB9 /* MVMCoreUI */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - D29DF0CA21E404D4003B2FB9 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D29DF25521E6A177003B2FB9 /* MFDigitTextField.xib in Resources */, - D29DF2AF21E7B3A4003B2FB9 /* MFTextView.xib in Resources */, - D29DF31C21ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf in Resources */, - D29DF24F21E6A177003B2FB9 /* MFTextField.xib in Resources */, - D29DF31D21ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf in Resources */, - D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */, - D29DF31A21ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf in Resources */, - D29DF32E21EE8C3D003B2FB9 /* Media.xcassets in Resources */, - D29DF31B21ECECC0003B2FB9 /* OCRAExtended.ttf in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - D29DF0C821E404D4003B2FB9 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */, - D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */, - DBC4391822442197001AB423 /* CaretView.swift in Sources */, - D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, - 012CA9BE2385C692003F810F /* ConstrainingMoleculeProtocol.swift in Sources */, - D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */, - 94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */, - 012CA98923849699003F810F /* SeperatorModel.swift in Sources */, - DBC4391922442197001AB423 /* DashLine.swift in Sources */, - 0AA33B34239813C50067DD0F /* UIColor+Extension.swift in Sources */, - 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, - D2FB151D23A40F1500C20E10 /* StackItem.swift in Sources */, - D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, - 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */, - 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */, - D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, - D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */, - D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */, - D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, - 0A209CD323A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift in Sources */, - 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, - D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */, - 017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */, - D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, - D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, - D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */, - D2B18B7F2360913400A9AEDC /* Control.swift in Sources */, - D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */, - DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */, - D224798C231450C8003FCCF9 /* HeadlineBodySwitch.swift in Sources */, - 017BEB442362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift in Sources */, - 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */, - D29DF17C21E69E1F003B2FB9 /* MFTextButton.m in Sources */, - 9445891F2385D2E900DE9FD4 /* CaretViewModel.swift in Sources */, - D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */, - D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, - 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */, - D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, - D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, - 017BEB3A2360EEB40024EF95 /* PageModel.swift in Sources */, - D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, - D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */, - 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */, - D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, - D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, - D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */, - 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, - 017BEB4023620A230024EF95 /* TextFieldModel.swift in Sources */, - D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, - D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */, - 94C2D9A723872DA90006CF46 /* LabelAttributeColorModel.swift in Sources */, - D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */, - 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */, - 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */, - D29DF25421E6A177003B2FB9 /* MFMdnTextField.m in Sources */, - D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, - 944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */, - D213347723843825008E41B3 /* Line.swift in Sources */, - D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */, - 01EB369023609801006832FA /* ListItemModel.swift in Sources */, - D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, - DBEFFA04225A829700230692 /* Label.swift in Sources */, - D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, - 01509D952327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift in Sources */, - D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, - 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */, - D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */, - D2B18B812360945C00A9AEDC /* View.swift in Sources */, - D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, - D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */, - D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */, - 012A88EE239858E300FE3DA1 /* ContainerMoleculeProtocol.swift in Sources */, - D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */, - D282AACB2243C61700C46919 /* ButtonView.swift in Sources */, - D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, - 01EB368F23609801006832FA /* LabelModel.swift in Sources */, - 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, - 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */, - D22479962316AF6E003FCCF9 /* HeadlineBodyTextButton.swift in Sources */, - 0AA33B36239813EE0067DD0F /* Color.swift in Sources */, - D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */, - 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */, - D29DF18121E69E50003B2FB9 /* MFView.m in Sources */, - D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */, - D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */, - 017BEB7B236763000024EF95 /* LineModel.swift in Sources */, - 94C2D9A523872C350006CF46 /* LabelAttributeFontModel.swift in Sources */, - 017BEB7F23676E870024EF95 /* MoleculeObjectMapping.swift in Sources */, - D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */, - D29DF2BF21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m in Sources */, - D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */, - 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */, - 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */, - D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, - 01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */, - D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, - D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, - 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */, - D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */, - D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */, - D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */, - D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */, - D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */, - D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, - D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */, - D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, - DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, - D224798A2314445E003FCCF9 /* LabelSwitch.swift in Sources */, - D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, - 017BEB4223620AD20024EF95 /* FormModelProtocol.swift in Sources */, - D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, - D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, - 017BEB4A236235BA0024EF95 /* ModelMoleculeViewProtocol.swift in Sources */, - 012CA99A2384A687003F810F /* MFTextField+ModelExtension.swift in Sources */, - 01EB3684236097C0006832FA /* MoleculeProtocol.swift in Sources */, - D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, - D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, - 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */, - D243859923A16B1800332775 /* Container.swift in Sources */, - D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */, - D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */, - 01EB369323609801006832FA /* HeaderModel.swift in Sources */, - D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, - 94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */, - D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */, - D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */, - 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */, - D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, - 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, - D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, - D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, - 94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */, - D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */, - D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */, - D29DF25121E6A177003B2FB9 /* MFDigitTextBox.m in Sources */, - DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */, - 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */, - D268C712238D6699007F2C1C /* DropDown.swift in Sources */, - 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */, - D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */, - D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */, - 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */, - 012CA99C23859FDC003F810F /* ViewConstrainingView+ModelExtension.swift in Sources */, - 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */, - D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */, - D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */, - D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */, - D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */, - D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, - D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */, - D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */, - 01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */, - 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */, - 01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */, - D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */, - D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */, - 946EE1BA237B66D80036751F /* ModelHelper.swift in Sources */, - 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */, - D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - D29DF32821EE8736003B2FB9 /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - D29DF32921EE8736003B2FB9 /* en */, - D29DF32A21EE8736003B2FB9 /* es */, - D29DF32B21EE8736003B2FB9 /* es-MX */, - ); - name = Localizable.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - D29DF0D221E404D4003B2FB9 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - D29DF0D321E404D4003B2FB9 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - D29DF0D521E404D4003B2FB9 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BITCODE_GENERATION_MODE = bitcode; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = FCMA4QKS77; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../SharedFrameworks"; - INFOPLIST_FILE = MVMCoreUI/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.vzw.MVMCoreUI; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - D29DF0D621E404D4003B2FB9 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BITCODE_GENERATION_MODE = bitcode; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = FCMA4QKS77; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../SharedFrameworks"; - INFOPLIST_FILE = MVMCoreUI/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.vzw.MVMCoreUI; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - D29DF0C621E404D4003B2FB9 /* Build configuration list for PBXProject "MVMCoreUI" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D29DF0D221E404D4003B2FB9 /* Debug */, - D29DF0D321E404D4003B2FB9 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - D29DF0D421E404D4003B2FB9 /* Build configuration list for PBXNativeTarget "MVMCoreUI" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D29DF0D521E404D4003B2FB9 /* Debug */, - D29DF0D621E404D4003B2FB9 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = D29DF0C321E404D4003B2FB9 /* Project object */; -} diff --git a/MVMCoreUI/Containers/Container.swift b/MVMCoreUI/Containers/Container.swift index 43fd62c8..a2e34a49 100644 --- a/MVMCoreUI/Containers/Container.swift +++ b/MVMCoreUI/Containers/Container.swift @@ -203,6 +203,7 @@ open class Container: View, ContainerProtocol { get { return model as? ContainerModelProtocol } } + // MARK:- ModelMoleculeViewProtocol override open func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let containerModel = model as? ContainerModelProtocol else { return } diff --git a/MVMCoreUI/Models/Molecules/NumberedListModel.swift b/MVMCoreUI/Models/Molecules/NumberedListModel.swift deleted file mode 100644 index 380c193f..00000000 --- a/MVMCoreUI/Models/Molecules/NumberedListModel.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// NumberedListModel.swift -// MVMCoreUI -// -// Created by Murugan, Vimal on 10/01/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -@objcMembers public class NumberedListModel: OrderListProtocol { - public var backgroundColor: Color? - public static var identifier: String = "numberedList" - public var list: [MoleculeProtocol] - - enum CodingKeys: String, CodingKey { - case list - } - - public required init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - list = try typeContainer.decodeMolecules(codingKey: .list) - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeModels(list, forKey: .list) - } -} - -public protocol OrderListProtocol: MoleculeProtocol { - var list: [MoleculeProtocol] {get} -} diff --git a/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift b/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift deleted file mode 100644 index 8d3280d9..00000000 --- a/MVMCoreUI/Models/Molecules/UnOrderedListModel.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// UnOrderedListModel.swift -// MVMCoreUI -// -// Created by Murugan, Vimal on 10/01/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -@objcMembers public class UnOrderedListModel: OrderListProtocol { - public var backgroundColor: Color? - public static var identifier: String = "unOrderedList" - public var bulletChar: String? - public var list: [MoleculeProtocol] - - enum CodingKeys: String, CodingKey { - case bulletChar - case list - } - - public required init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - bulletChar = try typeContainer.decodeIfPresent(String.self, forKey: .bulletChar) - list = try typeContainer.decodeMolecules(codingKey: .list) - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(bulletChar, forKey: .bulletChar) - try container.encodeModels(list, forKey: .list) - } -} diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift index 31091796..72aceab7 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChartView.swift @@ -94,12 +94,12 @@ extension DoughnutChartView: MVMCoreUIViewConstrainingProtocol { } class ColorViewLabelsStack: MoleculeStackView { - override func createStackItemsFromModel(with delegate: MVMCoreUIDelegateObject?) { + override func createStackItemsFromModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { let view = ColorViewWithLabel() let stackItem = MoleculeStackItem(andContain: view) - stackItem.setWithModel(model, delegate, nil) + stackItem.setWithModel(model, delegateObject, additionalData) stackItems.append(stackItem) } } diff --git a/MVMCoreUI/Molecules/Items/StackItemModel.swift b/MVMCoreUI/Molecules/Items/StackItemModel.swift index 9ab86687..9484cd8d 100644 --- a/MVMCoreUI/Molecules/Items/StackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/StackItemModel.swift @@ -8,7 +8,9 @@ import Foundation -@objcMembers public class StackItemModel: StackItemModelProtocol, Codable { +@objcMembers public class StackItemModel: StackItemModelProtocol, MoleculeProtocol { + public static var identifier: String = "simpleStackItem" + public var backgroundColor: Color? public var spacing: CGFloat? public var percent: Int? public var gone: Bool = false diff --git a/MVMCoreUI/Molecules/Items/StackItemModelProtocol.swift b/MVMCoreUI/Molecules/Items/StackItemModelProtocol.swift index 2223ed39..165cb1ac 100644 --- a/MVMCoreUI/Molecules/Items/StackItemModelProtocol.swift +++ b/MVMCoreUI/Molecules/Items/StackItemModelProtocol.swift @@ -8,7 +8,7 @@ import Foundation -public protocol StackItemModelProtocol { +public protocol StackItemModelProtocol: MoleculeProtocol { var spacing: CGFloat? { get set } var percent: Int? { get set } var gone: Bool { get set } diff --git a/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift b/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift deleted file mode 100644 index 693df09c..00000000 --- a/MVMCoreUI/Molecules/LabelRightMoleculesStack.swift +++ /dev/null @@ -1,167 +0,0 @@ -// -// ListMoleculeContainer.swift -// MVMCoreUI -// -// Created by Murugan, Vimal on 03/01/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import UIKit - -open class LabelRightMoleculesStack: MoleculeStackView { - - var orderedListModel: OrderListProtocol? - - public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - let previousModel = self.orderedListModel - //Remove previously drawn views - removeAllItemViews() - guard let orderedListModel = model as? OrderListProtocol else { - return - } - - var items: [StackItem]? - if previousModel?.list.count == orderedListModel.list.count { - items = stackItems - } - stackItems = [] - self.model = MoleculeStackModel(molecules: []) - for (index, labelModel) in orderedListModel.list.enumerated() { - let labelContainer = items?[index].view as? LeftLabelRightMoleculeContainer ?? LeftLabelRightMoleculeContainer() - labelContainer.leftText = leftTextForIndex(index) - labelContainer.setWithModel(labelModel, delegateObject, additionalData) - addView(labelContainer, lastItem: index == orderedListModel.list.count - 1) - } - self.orderedListModel = orderedListModel - restack() - } - - //MARK: - Subclass should overirde this - func leftTextForIndex(_ index: Int) -> String { - return "" - } -} - -class LeftLabelRightMoleculeContainer: View { - - var label = Label.commonLabelB2(true) - var rightContainer = MVMCoreUICommonViewsUtility.commonView() - var leftContainer = MVMCoreUICommonViewsUtility.commonView() - var rightMoleculeName: String? - var rightMolecule: View? - var leftText: String? - var leftWidthConstraint: NSLayoutConstraint? - var percentage: CGFloat = 5 - - var constraintBtwViews: NSLayoutConstraint? - var spaceBtwViews: CGFloat = 0 { - didSet { - if spaceBtwViews != oldValue { - constraintBtwViews?.constant = spaceBtwViews - setNeedsDisplay() - } - } - } - - // MARK: - Inits - public convenience init() { - self.init(frame:.zero) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - public required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func setupView() { - super.setupView() - - guard rightContainer.superview == nil else { - return - } - - translatesAutoresizingMaskIntoConstraints = false - addSubview(rightContainer) - addSubview(leftContainer) - leftContainer.addSubview(label) - - NSLayoutConstraint.constraintPinSubview(label, pinTop: true, pinBottom: false, pinLeft: true, pinRight: false) - leftContainer.rightAnchor.constraint(greaterThanOrEqualTo: label.rightAnchor).isActive = true - leftContainer.bottomAnchor.constraint(greaterThanOrEqualTo: label.bottomAnchor).isActive = true - - let lowRightConstraint = leftContainer.rightAnchor.constraint(equalTo: label.rightAnchor) - lowRightConstraint.priority = UILayoutPriority(rawValue: 200) - lowRightConstraint.isActive = true - - let lowBottomConstraint = leftContainer.bottomAnchor.constraint(equalTo: label.bottomAnchor) - lowBottomConstraint.priority = UILayoutPriority(rawValue: 200) - lowBottomConstraint.isActive = true - - NSLayoutConstraint.constraintPinSubview(leftContainer, pinTop: true, pinBottom: false, pinLeft: true, pinRight: false) - bottomAnchor.constraint(greaterThanOrEqualTo: leftContainer.bottomAnchor).isActive = true - - NSLayoutConstraint.constraintPinSubview(rightContainer, pinTop: true, pinBottom: true, pinLeft: false, pinRight: true) - constraintBtwViews = rightContainer.leftAnchor.constraint(equalTo: leftContainer.rightAnchor, constant: spaceBtwViews) - constraintBtwViews?.priority = .required - constraintBtwViews?.isActive = true - - setContentHuggingPriority(.defaultHigh, for: .vertical) - setContentHuggingPriority(.defaultHigh, for: .horizontal) - updateLeftViewWidthConstraint(percentage) - - } - - override func updateView(_ size: CGFloat) { - super.updateView(size) - rightMolecule?.updateView(size) - label.updateView(size) - updateLeftViewWidthConstraint(percentage) - setNeedsDisplay() - } - - override func reset() { - super.reset() - rightMolecule?.reset() - } - - public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - let previousMoleculeName = self.rightMoleculeName - super.setWithModel(model, delegateObject, additionalData) - removeSubviewsInRightContainer() - label.text = leftText - rightMoleculeName = model?.moleculeName - guard let validModel = model else { - return - } - //For reuse purpose check that allready added molecule is same - if let rightMolecule = self.rightMolecule, previousMoleculeName == rightMoleculeName { - rightMolecule.setWithModel(validModel, delegateObject, additionalData) - addView(rightMolecule) - } else { - if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(validModel, delegateObject, false) { - addView(molecule) - } - } - } - - func updateLeftViewWidthConstraint(_ percent: CGFloat) { - percentage = percent - leftWidthConstraint?.isActive = false - leftWidthConstraint = leftContainer.widthAnchor.constraint(equalTo: widthAnchor, multiplier: CGFloat(percent/100), constant: 0) - leftWidthConstraint?.isActive = true - } - - func removeSubviewsInRightContainer() { - rightContainer.subviews.forEach({ $0.removeFromSuperview() }) - } - - func addView(_ view: UIView) { - view.translatesAutoresizingMaskIntoConstraints = false - rightContainer.addSubview(view) - NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: true, pinRight: true) - rightMolecule = view as? View - } -} diff --git a/MVMCoreUI/Molecules/MoleculeContainer.swift b/MVMCoreUI/Molecules/MoleculeContainer.swift index e3646bcf..dc70e38d 100644 --- a/MVMCoreUI/Molecules/MoleculeContainer.swift +++ b/MVMCoreUI/Molecules/MoleculeContainer.swift @@ -42,4 +42,28 @@ open class MoleculeContainer: Container { } super.setWithModel(model, delegateObject, additionalData) } + + public override static func nameForReuse(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + guard let containerModel = model as? MoleculeContainerModel, + let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(containerModel.molecule) as? ModelMoleculeViewProtocol.Type, + let moleculeName = moleculeClass.nameForReuse(containerModel.molecule, delegateObject) else { + return "\(model?.moleculeName ?? "moleculeContainer")<>" + } + return "\(model?.moleculeName ?? "moleculeContainer")<\(moleculeName)>" + } + + public override class func estimatedHeight(forRow molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let containerModel = molecule as? MoleculeContainerModel else { return 0 } + guard let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(containerModel.molecule) as? ModelMoleculeViewProtocol.Type, + let moleculeHeight = moleculeClass.estimatedHeight(forRow: containerModel.molecule, delegateObject: delegateObject) else { + return (containerModel.topMarginPadding ?? 0) + (containerModel.bottomMarginPadding ?? 0) + } + return moleculeHeight + (containerModel.topMarginPadding ?? 0) + (containerModel.bottomMarginPadding ?? 0) + } + + public override class func requiredModules(_ molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let containerModel = molecule as? MoleculeContainerModel, + let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(containerModel.molecule) as? ModelMoleculeViewProtocol.Type else { return nil } + return moleculeClass.requiredModules(containerModel.molecule, delegateObject: delegateObject, error: error) + } } diff --git a/MVMCoreUI/Molecules/NumberedList.swift b/MVMCoreUI/Molecules/NumberedList.swift deleted file mode 100644 index 376dffc0..00000000 --- a/MVMCoreUI/Molecules/NumberedList.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// NumberedList.swift -// MVMCoreUI -// -// Created by Murugan, Vimal on 03/01/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import UIKit - -open class NumberedList: LabelRightMoleculesStack { - - //MARK:- Super class override methods - override func leftTextForIndex(_ index: Int) -> String { - return String(index+1) + "." - } - -} diff --git a/MVMCoreUI/Molecules/UnOrderedList.swift b/MVMCoreUI/Molecules/UnOrderedList.swift deleted file mode 100644 index 4f85a483..00000000 --- a/MVMCoreUI/Molecules/UnOrderedList.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// UnOrderedList.swift -// MVMCoreUI -// -// Created by Murugan, Vimal on 03/01/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import UIKit - -open class UnOrderedList: LabelRightMoleculesStack { - - //MARK:- Super class override methods - override func leftTextForIndex(_ index: Int) -> String { - return (orderedListModel as? UnOrderedListModel)?.bulletChar ?? "•" - } - -} diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedList.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedList.swift new file mode 100644 index 00000000..8f977ed7 --- /dev/null +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedList.swift @@ -0,0 +1,14 @@ +// +// NumberedList.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 03/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class NumberedList: StringAndMoleculeStack { +} + + diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift new file mode 100644 index 00000000..728ae3a8 --- /dev/null +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift @@ -0,0 +1,47 @@ +// +// NumberedListModel.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 10/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class NumberedListModel: MoleculeStackModel { + public override class var identifier: String { + return "numberedList" + } + + private enum NumberedListCodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case list + } + + // Numbered list model comes in the from of list = [MoleculeProtocol] + public required init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: NumberedListCodingKeys.self) + + let list = try typeContainer.decodeMolecules(codingKey: .list) + var models: [MoleculeStackItemModel] = [] + for (index, molecule) in list.enumerated() { + models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: "\(index).", molecule: molecule))) + } + super.init(molecules: models) + spacing = 0 + } + + public override func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: NumberedListCodingKeys.self) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + + var models: [MoleculeProtocol] = [] + for molecule in molecules { + models.append(molecule.molecule) + } + try container.encodeModels(models, forKey: .list) + } +} + + diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift new file mode 100644 index 00000000..f2c73cab --- /dev/null +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift @@ -0,0 +1,42 @@ +// +// StringAndMoleculeModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/17/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class StringAndMoleculeModel: MoleculeProtocol { + public static var identifier: String = "stringAndMoleculeModel" + public var backgroundColor: Color? + public var string: String + public var molecule: MoleculeProtocol + + public init(string: String, molecule: MoleculeProtocol) { + self.string = string + self.molecule = molecule + } + + enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case string + case molecule + } + + public required init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + string = try typeContainer.decode(String.self, forKey: .string) + molecule = try typeContainer.decodeMolecule(codingKey: .molecule) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encode(string, forKey: .string) + try container.encodeModel(molecule, forKey: .molecule) + } +} diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift new file mode 100644 index 00000000..2606ecf4 --- /dev/null +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift @@ -0,0 +1,28 @@ +// +// ListMoleculeContainer.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 03/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +// This class is only temporarily necessary. Eventually we will have initWithModel instad of just init for moleculeviews, which will remove this need. +open class StringAndMoleculeStack: MoleculeStackView { + override func createStackItemsFromModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + guard let model = stackModel else { return } + for stackItemModel in model.molecules { + guard let stringAndMoleculeModel = stackItemModel.molecule as? StringAndMoleculeModel, + let moleculeName = stringAndMoleculeModel.molecule.moleculeName, + let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forName: moleculeName) as? (UIView & ModelMoleculeViewProtocol) else { + // Throw error + return + } + let view = StringAndMoleculeView(string: stringAndMoleculeModel.string, molecule: molecule) + let stackItem = MoleculeStackItem(andContain: view) + stackItem.setWithModel(stackItemModel, delegateObject, nil) + stackItems.append(stackItem) + } + } +} diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift new file mode 100644 index 00000000..1874c163 --- /dev/null +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift @@ -0,0 +1,92 @@ +// +// StringAndMoleculeView.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/17/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class StringAndMoleculeView: View { + var label = Label.commonLabelB2(true) + var string: String + var molecule: UIView & ModelMoleculeViewProtocol + + var leftWidthConstraint: NSLayoutConstraint? + @Percent var percentage: CGFloat = 5 + + var constraintBetweenViews: NSLayoutConstraint? + var spaceBetweenViews: CGFloat = 0 { + didSet { + if spaceBetweenViews != oldValue { + constraintBetweenViews?.constant = spaceBetweenViews + setNeedsDisplay() + } + } + } + + // MARK: - Inits + public init(string: String, molecule: UIView & ModelMoleculeViewProtocol) { + self.string = string + self.molecule = molecule + super.init(frame: .zero) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func setupView() { + super.setupView() + guard subviews.count == 0 else { + return + } + + translatesAutoresizingMaskIntoConstraints = false + addSubview(label) + addSubview(molecule) + + NSLayoutConstraint.constraintPinSubview(label, pinTop: true, pinBottom: false, pinLeft: true, pinRight: false) + bottomAnchor.constraint(greaterThanOrEqualTo: label.bottomAnchor).isActive = true + + let lowBottomConstraint = bottomAnchor.constraint(equalTo: label.bottomAnchor) + lowBottomConstraint.priority = UILayoutPriority(rawValue: 200) + lowBottomConstraint.isActive = true + + NSLayoutConstraint.constraintPinSubview(molecule, pinTop: true, pinBottom: true, pinLeft: false, pinRight: true) + constraintBetweenViews = molecule.leftAnchor.constraint(equalTo: label.rightAnchor, constant: spaceBetweenViews) + constraintBetweenViews?.priority = .required + constraintBetweenViews?.isActive = true + + setContentHuggingPriority(.defaultHigh, for: .vertical) + setContentHuggingPriority(.defaultHigh, for: .horizontal) + updateLeftViewWidthConstraint(percentage) + } + + override open func updateView(_ size: CGFloat) { + super.updateView(size) + (molecule as? MVMCoreViewProtocol)?.updateView(size) + label.updateView(size) + } + + override open func reset() { + super.reset() + label.reset() + (molecule as? MoleculeViewProtocol)?.reset?() + } + + public override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? StringAndMoleculeModel else { return } + label.text = model.string + molecule.setWithModel(model.molecule, delegateObject, additionalData) + } + + func updateLeftViewWidthConstraint(_ percent: CGFloat) { + percentage = percent + leftWidthConstraint?.isActive = false + leftWidthConstraint = label.widthAnchor.constraint(equalTo: widthAnchor, multiplier: CGFloat(percent/100), constant: 0) + leftWidthConstraint?.isActive = true + } +} diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedList.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedList.swift new file mode 100644 index 00000000..b393866c --- /dev/null +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedList.swift @@ -0,0 +1,12 @@ +// +// UnOrderedList.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 03/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class UnOrderedList: StringAndMoleculeStack { +} diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift new file mode 100644 index 00000000..a905401c --- /dev/null +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift @@ -0,0 +1,51 @@ +// +// UnOrderedListModel.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 10/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class UnOrderedListModel: MoleculeStackModel { + public override class var identifier: String { + return "unOrderedList" + } + public var bulletChar = "•" + + private enum NumberedListCodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case list + case bulletChar + } + + // Numbered list model comes in the from of list = [MoleculeProtocol] + public required init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: NumberedListCodingKeys.self) + if let bulletChar = try typeContainer.decodeIfPresent(String.self, forKey: .bulletChar) { + self.bulletChar = bulletChar + } + + let list = try typeContainer.decodeMolecules(codingKey: .list) + var models: [MoleculeStackItemModel] = [] + for molecule in list { + models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: bulletChar, molecule: molecule))) + } + super.init(molecules: models) + spacing = 0 + } + + public override func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: NumberedListCodingKeys.self) + try container.encode(bulletChar, forKey: .bulletChar) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + + var models: [MoleculeProtocol] = [] + for molecule in molecules { + models.append(molecule.molecule) + } + try container.encodeModels(models, forKey: .list) + } +} diff --git a/MVMCoreUI/Organisms/MoleculeStackModel.swift b/MVMCoreUI/Organisms/MoleculeStackModel.swift index 7136718c..5f33725e 100644 --- a/MVMCoreUI/Organisms/MoleculeStackModel.swift +++ b/MVMCoreUI/Organisms/MoleculeStackModel.swift @@ -10,7 +10,9 @@ import Foundation @objcMembers public class MoleculeStackModel: ContainerModel, MoleculeProtocol, StackModelProtocol { - public static var identifier: String = "stack" + public class var identifier: String { + return "stack" + } public var backgroundColor: Color? public var molecules: [MoleculeStackItemModel] public var axis: NSLayoutConstraint.Axis = .vertical diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index a7dd1640..aa81ff80 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -23,10 +23,10 @@ open class MoleculeStackView: Stack { // MARK: - Adding to stack /// Creates all of the stackItems for the stackItemModels - override func createStackItemsFromModel(with delegate: MVMCoreUIDelegateObject?) { + override func createStackItemsFromModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { - if let stackItem = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model, delegate) as? MoleculeStackItem { + if let stackItem = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model, delegateObject) as? MoleculeStackItem { stackItems.append(stackItem) } } diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index 0fc1ca8f..572c772f 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -94,38 +94,26 @@ open class Stack: Container where T: StackModelProtocol { removeAllItemViews() // If the items in the stack are different, clear them, create new ones. - if (previousModel == nil) || MoleculeStackView.nameForReuse(previousModel, delegateObject) != MoleculeStackView.nameForReuse(model, delegateObject) { + if (previousModel == nil) || Self.nameForReuse(previousModel, delegateObject) != Self.nameForReuse(model, delegateObject) { stackItems = [] - createStackItemsFromModel(with: delegateObject) - } else if let models = stackModel?.molecules { - for (index, element) in models.enumerated() { - (stackItems[index] as? ModelMoleculeViewProtocol)?.setWithModel(element as? MoleculeProtocol, delegateObject, additionalData) - } + createStackItemsFromModel(model, delegateObject, additionalData) + } else { + setStackItemsFromModel(model, delegateObject, additionalData) } restack() } - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - if let model = model { - setWithModel(model, delegateObject, additionalData) - } else if let json = json, - let data = try? JSONSerialization.data(withJSONObject: json), - let model = try? JSONDecoder().decode(MoleculeStackModel.self, from: data) { - setWithModel(model, delegateObject, additionalData) - } - } - public override class func nameForReuse(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { // This will aggregate names of molecules to make an id. - guard let model = model as? MoleculeStackModel else { + guard let model = model as? T else { return "stack<>" } var name = "stack<" for case let item in model.molecules { - if let moleculeName = item.molecule.moleculeName { + if let moleculeName = item.moleculeName { if let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? ModelMoleculeViewProtocol.Type, - let nameForReuse = moleculeClass.nameForReuse(item.molecule, delegateObject) { + let nameForReuse = moleculeClass.nameForReuse(item, delegateObject) { name.append(nameForReuse + ",") } else { name.append(moleculeName + ",") @@ -138,7 +126,7 @@ open class Stack: Container where T: StackModelProtocol { // Need to update to take into account first spacing flag public override class func estimatedHeight(forRow molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - guard let model = molecule as? MoleculeStackModel else { return 0 } + guard let model = molecule as? T else { return 0 } let horizontal = model.axis == .horizontal var estimatedHeight: CGFloat = 0 for case let item in model.molecules { @@ -157,7 +145,7 @@ open class Stack: Container where T: StackModelProtocol { } public override class func requiredModules(_ molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let model = molecule as? MoleculeStackModel else { return nil } + guard let model = molecule as? T else { return nil } var modules: [String] = [] for case let item in model.molecules { if let modulesForMolecule = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.requiredModules(item, delegateObject: delegateObject, error: error) { @@ -167,11 +155,21 @@ open class Stack: Container where T: StackModelProtocol { return modules.count > 0 ? modules : nil } - // MARK: - Adding to stack + // MARK: - Subclassables + /// Can be subclassed to create views when we get stack item models and have no views yet - func createStackItemsFromModel(with delegate: MVMCoreUIDelegateObject?) { + func createStackItemsFromModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { } + /// Can be subclassed to set stack items with model when we already have views + func setStackItemsFromModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + guard let models = stackModel?.molecules else { return } + for (index, element) in models.enumerated() { + (stackItems[index] as? ModelMoleculeViewProtocol)?.setWithModel(element, delegateObject, additionalData) + } + } + + // MARK: - Adding to stack /// Convenience function, adds a view to a StackItem to the Stack func addViewToItemToStack(_ view: UIView, lastItem: Bool) { let stackItemModel = StackItemModel() diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 5199cf96..1eda2454 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -72,8 +72,6 @@ @"headlineBodyButton": HeadlineBodyButton.class, @"stackItem": MoleculeStackItem.class, @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class, - @"unOrderedList": UnOrderedList.class, - @"numberedList": NumberedList.class, @"headlineBodyCaretLinkImage" : HeadLineBodyCaretLinkImage.class, @"doughnutChart": DoughnutChartView.class, @"headLineBodyCaretLinkImage" : HeadLineBodyCaretLinkImage.class diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index b81c6e08..b12145f2 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -11,13 +11,23 @@ import Foundation @objcMembers public class MoleculeObjectMapping: NSObject { public static func registerObjects() { let mapping = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping - mapping?.setObject(MoleculeStackView.self, forKey: "stack" as NSString) - + ModelRegistry.register(MoleculeStackModel.self) + mapping?.setObject(MoleculeStackView.self, forKey: MoleculeStackModel.identifier as NSString) + ModelRegistry.register(StackModel.self) + mapping?.setObject(Stack.self, forKey: StackModel.identifier as NSString) + ModelRegistry.register(StackItemModel.self) + mapping?.setObject(StackItem.self, forKey: StackItemModel.identifier as NSString) + ModelRegistry.register(StringAndMoleculeModel.self) + mapping?.setObject(StringAndMoleculeView.self, forKey: StringAndMoleculeModel.identifier as NSString) + ModelRegistry.register(UnOrderedListModel.self) + mapping?.setObject(UnOrderedList.self, forKey: UnOrderedListModel.identifier as NSString) + ModelRegistry.register(NumberedListModel.self) + mapping?.setObject(NumberedList.self, forKey: NumberedListModel.identifier as NSString) + ModelRegistry.register(LabelModel.self) ModelRegistry.register(HeaderModel.self) ModelRegistry.register(FooterModel.self) ModelRegistry.register(HeadlineBodyModel.self) - ModelRegistry.register(MoleculeStackModel.self) ModelRegistry.register(MoleculeStackItemModel.self) ModelRegistry.register(TextFieldModel.self) ModelRegistry.register(ProgressBarModel.self) From d80ae0bd04989a851c8e425fd442b4e903c4c7f2 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 17 Jan 2020 14:07:31 -0500 Subject: [PATCH 52/59] more label fix --- MVMCoreUI/Atoms/Views/Label.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index b4173add..2188b2a2 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -263,13 +263,13 @@ public typealias ActionBlock = () -> () } if let attributes = labelModel.attributes, let labelText = text { - let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font as UIFont, NSAttributedString.Key.foregroundColor: textColor as UIColor]) + let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font.withSize(standardFontSize), NSAttributedString.Key.foregroundColor: textColor as UIColor]) for attribute in attributes { let range = NSRange(location: attribute.location, length: attribute.length) switch attribute { - case let _ as LabelAttributeUnderlineModel: + case _ as LabelAttributeUnderlineModel: attributedString.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range) - case let _ as LabelAttributeStrikeThroughModel: + case _ as LabelAttributeStrikeThroughModel: attributedString.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.thick.rawValue, range: range) attributedString.addAttribute(.baselineOffset, value: 0, range: range) case let colorAtt as LabelAttributeColorModel: From 19d3b960ae2c47f8e5cb168f552b53fe72cf0785 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 17 Jan 2020 14:10:26 -0500 Subject: [PATCH 53/59] button alignment --- .../HorizontalCombinationViews/TwoButtonView.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 47e67724..a50e9488 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -93,7 +93,7 @@ import UIKit viewForButtons.addSubview(secondaryButton) secondaryButton.widthAnchor.constraint(equalTo: primaryButton.widthAnchor, multiplier: 1).isActive = true NSLayoutConstraint.constraintPinSubview(primaryButton, pinTop: true, pinBottom: true, pinLeft: true, pinRight: false) - NSLayoutConstraint.constraintPinSubview(secondaryButton, pinTop: true, pinBottom: false, pinLeft: false, pinRight: true) + NSLayoutConstraint.constraintPinSubview(secondaryButton, pinTop: false, pinBottom: false, pinLeft: false, pinRight: true) let constraint = secondaryButton.leadingAnchor.constraint(equalTo: primaryButton.trailingAnchor, constant: 10) constraint.priority = UILayoutPriority(900) constraint.isActive = true @@ -257,6 +257,10 @@ import UIKit primaryButton?.isHidden = true secondaryButton?.isHidden = true } + + override open func horizontalAlignment() -> UIStackView.Alignment { + return .center + } } // MARK: - Deprecate From 9e789e23122128e7fbccbbbcfe04165f7c627f35 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 17 Jan 2020 14:11:37 -0500 Subject: [PATCH 54/59] secondary --- .../Molecules/HorizontalCombinationViews/TwoButtonView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index a50e9488..ddfd89de 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -309,6 +309,7 @@ extension TwoButtonView: ModelMoleculeViewProtocol { setDefaultCustom() primaryButton?.setWithModel(model.primaryButton, delegateObject, additionalData) secondaryButton?.setWithModel(model.secondaryButton, delegateObject, additionalData) + secondaryButton?.setAsSecondaryCustom() super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) } } From dc19d850c1275e83f2d89b6792c5c1b587852846 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 17 Jan 2020 14:12:51 -0500 Subject: [PATCH 55/59] setDefaultCustom --- .../Molecules/HorizontalCombinationViews/TwoButtonView.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index ddfd89de..c6111c74 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -306,10 +306,9 @@ extension TwoButtonView: ModelMoleculeViewProtocol { public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let model = model as? TwoButtonViewModel else { return } setupUI(primaryButtonShowing: model.primaryButton != nil, secondaryButtonShowing: model.secondaryButton != nil) - setDefaultCustom() primaryButton?.setWithModel(model.primaryButton, delegateObject, additionalData) secondaryButton?.setWithModel(model.secondaryButton, delegateObject, additionalData) - secondaryButton?.setAsSecondaryCustom() + setDefaultCustom() super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) } } From 69c86c4479572639c5b29bd60ed0585a1b6afc47 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 17 Jan 2020 14:15:37 -0500 Subject: [PATCH 56/59] flip button position --- .../HorizontalCombinationViews/TwoButtonView.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index c6111c74..eae223d2 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -92,9 +92,9 @@ import UIKit viewForButtons.addSubview(primaryButton) viewForButtons.addSubview(secondaryButton) secondaryButton.widthAnchor.constraint(equalTo: primaryButton.widthAnchor, multiplier: 1).isActive = true - NSLayoutConstraint.constraintPinSubview(primaryButton, pinTop: true, pinBottom: true, pinLeft: true, pinRight: false) - NSLayoutConstraint.constraintPinSubview(secondaryButton, pinTop: false, pinBottom: false, pinLeft: false, pinRight: true) - let constraint = secondaryButton.leadingAnchor.constraint(equalTo: primaryButton.trailingAnchor, constant: 10) + NSLayoutConstraint.constraintPinSubview(primaryButton, pinTop: true, pinBottom: true, pinLeft: false, pinRight: true) + NSLayoutConstraint.constraintPinSubview(secondaryButton, pinTop: false, pinBottom: false, pinLeft: true, pinRight: false) + let constraint = primaryButton.leadingAnchor.constraint(equalTo: secondaryButton.trailingAnchor, constant: 10) constraint.priority = UILayoutPriority(900) constraint.isActive = true } From c2f3a7a2db4b31fac31b031afa94b8ccf79d0eef Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 17 Jan 2020 14:31:32 -0500 Subject: [PATCH 57/59] primary button and top bottom pin --- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 2 +- .../Molecules/HorizontalCombinationViews/TwoButtonView.swift | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index 64d9a3c3..b480aa2c 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -23,7 +23,7 @@ public class ButtonModel: MoleculeProtocol { public var backgroundColor: Color? public var title: String public var action: ActionProtocol - public var style: ButtonStyle? = .primary + public var style: ButtonStyle? public var size: ButtonSize? = .standard public var required: Bool? public var requiredGroups: [String]? diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index eae223d2..f1c5c6a8 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -92,8 +92,8 @@ import UIKit viewForButtons.addSubview(primaryButton) viewForButtons.addSubview(secondaryButton) secondaryButton.widthAnchor.constraint(equalTo: primaryButton.widthAnchor, multiplier: 1).isActive = true + NSLayoutConstraint.constraintPinSubview(secondaryButton, pinTop: true, pinBottom: true, pinLeft: true, pinRight: false) NSLayoutConstraint.constraintPinSubview(primaryButton, pinTop: true, pinBottom: true, pinLeft: false, pinRight: true) - NSLayoutConstraint.constraintPinSubview(secondaryButton, pinTop: false, pinBottom: false, pinLeft: true, pinRight: false) let constraint = primaryButton.leadingAnchor.constraint(equalTo: secondaryButton.trailingAnchor, constant: 10) constraint.priority = UILayoutPriority(900) constraint.isActive = true @@ -308,7 +308,6 @@ extension TwoButtonView: ModelMoleculeViewProtocol { setupUI(primaryButtonShowing: model.primaryButton != nil, secondaryButtonShowing: model.secondaryButton != nil) primaryButton?.setWithModel(model.primaryButton, delegateObject, additionalData) secondaryButton?.setWithModel(model.secondaryButton, delegateObject, additionalData) - setDefaultCustom() super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) } } From 9e066be3fa90fa3265d193c676fa01102ce88c50 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 17 Jan 2020 14:53:23 -0500 Subject: [PATCH 58/59] setDefaultCustom --- .../Molecules/HorizontalCombinationViews/TwoButtonView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index f1c5c6a8..1559e1a5 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -306,6 +306,7 @@ extension TwoButtonView: ModelMoleculeViewProtocol { public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let model = model as? TwoButtonViewModel else { return } setupUI(primaryButtonShowing: model.primaryButton != nil, secondaryButtonShowing: model.secondaryButton != nil) + setDefaultCustom() primaryButton?.setWithModel(model.primaryButton, delegateObject, additionalData) secondaryButton?.setWithModel(model.secondaryButton, delegateObject, additionalData) super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) From 299a519e20009a22e18d70fad5a7db125c99ea79 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 17 Jan 2020 15:56:48 -0500 Subject: [PATCH 59/59] Default alignment fix --- MVMCoreUI/Containers/Container.swift | 2 +- MVMCoreUI/Containers/ContainerProtocol.swift | 1 + MVMCoreUI/Organisms/Stack.swift | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Containers/Container.swift b/MVMCoreUI/Containers/Container.swift index a2e34a49..42a53848 100644 --- a/MVMCoreUI/Containers/Container.swift +++ b/MVMCoreUI/Containers/Container.swift @@ -197,7 +197,7 @@ public class ContainerHelper: NSObject { } open class Container: View, ContainerProtocol { - var view: UIView? + public var view: UIView? let containerHelper = ContainerHelper() var containerModel: ContainerModelProtocol? { get { return model as? ContainerModelProtocol } diff --git a/MVMCoreUI/Containers/ContainerProtocol.swift b/MVMCoreUI/Containers/ContainerProtocol.swift index 8079ca24..10bac27c 100644 --- a/MVMCoreUI/Containers/ContainerProtocol.swift +++ b/MVMCoreUI/Containers/ContainerProtocol.swift @@ -9,6 +9,7 @@ import Foundation public protocol ContainerProtocol { + var view: UIView? { get set } func alignHorizontal(_ alignment: UIStackView.Alignment) func alignVertical(_ alignment: UIStackView.Alignment) func constrainView(_ view: UIView) diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index 572c772f..f67f7a0e 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -190,8 +190,8 @@ open class Stack: Container where T: StackModelProtocol { let spacing = model.spacing ?? stackModel.spacing if let container = view as? ContainerProtocol { - let verticalAlignment = (model as? ContainerModelProtocol)?.verticalAlignment ?? (view as? MVMCoreUIViewConstrainingProtocol)?.verticalAlignment?() ?? (model.percent == nil && stackModel.axis == .vertical ? .fill : (stackModel.axis == .vertical ? .leading : .center)) - let horizontalAlignment = (model as? ContainerModelProtocol)?.horizontalAlignment ?? (view as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() ?? (stackModel.axis == .vertical || model.percent == nil ? .fill : .leading) + let verticalAlignment = (model as? ContainerModelProtocol)?.verticalAlignment ?? (container.view as? MVMCoreUIViewConstrainingProtocol)?.verticalAlignment?() ?? (model.percent == nil && stackModel.axis == .vertical ? .fill : (stackModel.axis == .vertical ? .leading : .center)) + let horizontalAlignment = (model as? ContainerModelProtocol)?.horizontalAlignment ?? (container.view as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() ?? (stackModel.axis == .vertical || model.percent == nil ? .fill : .leading) container.alignHorizontal(horizontalAlignment) container.alignVertical(verticalAlignment) }