From 5ce98da559b77bf2b8c422b19f24a0eb7c5bf67d Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 10 Apr 2020 16:59:40 -0400 Subject: [PATCH] improvements --- MVMCoreUI.xcodeproj/project.pbxproj | 24 ++- MVMCoreUI/Atomic/Atoms/Views/RadioBox.swift | 159 +++++++++++++++++ .../Views/RadioBoxCollectionViewCell.swift | 165 +----------------- .../Atomic/Atoms/Views/RadioBoxModel.swift | 13 +- MVMCoreUI/Atomic/Atoms/Views/RadioBoxes.swift | 11 +- .../Atomic/Atoms/Views/RadioBoxesModel.swift | 22 ++- MVMCoreUI/Atomic/Organisms/Carousel.swift | 4 - MVMCoreUI/BaseClasses/CollectionView.swift | 46 +++++ ...ProgrammaticCollectionViewController.swift | 7 +- 9 files changed, 255 insertions(+), 196 deletions(-) create mode 100644 MVMCoreUI/Atomic/Atoms/Views/RadioBox.swift create mode 100644 MVMCoreUI/BaseClasses/CollectionView.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 0cd70ea2..0af01831 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -202,7 +202,6 @@ BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */; }; BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */; }; BB6C6AC924225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShortModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6AC72422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShortModel.swift */; }; - BBAA4F02243D8E3B005AAD5F /* RadioBoxCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBAA4EFE243D8E3A005AAD5F /* RadioBoxCollectionViewCell.swift */; }; BBAA4F03243D8E3B005AAD5F /* RadioBoxes.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBAA4EFF243D8E3B005AAD5F /* RadioBoxes.swift */; }; BBAA4F04243D8E3B005AAD5F /* RadioBoxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBAA4F00243D8E3B005AAD5F /* RadioBoxModel.swift */; }; BBAA4F05243D8E3B005AAD5F /* RadioBoxesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBAA4F01243D8E3B005AAD5F /* RadioBoxesModel.swift */; }; @@ -268,6 +267,9 @@ D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FAA0243CF66B00D98315 /* ContainerCollectionReusableView.swift */; }; D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FAA2243E632F00D98315 /* ProgrammaticCollectionViewController.swift */; }; D264FAA5243F66A500D98315 /* CollectionTemplateItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FAA4243F66A500D98315 /* CollectionTemplateItemProtocol.swift */; }; + D264FAA7243FE13B00D98315 /* RadioBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FAA6243FE13B00D98315 /* RadioBox.swift */; }; + D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FAA92440F97600D98315 /* CollectionView.swift */; }; + D264FAAC2441009400D98315 /* RadioBoxCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FAAB2441009400D98315 /* RadioBoxCollectionViewCell.swift */; }; D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; }; D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; }; D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */; }; @@ -626,7 +628,6 @@ BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTall.swift; sourceTree = ""; }; BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerShort.swift; sourceTree = ""; }; BB6C6AC72422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShortModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerShortModel.swift; sourceTree = ""; }; - BBAA4EFE243D8E3A005AAD5F /* RadioBoxCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioBoxCollectionViewCell.swift; sourceTree = ""; }; BBAA4EFF243D8E3B005AAD5F /* RadioBoxes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioBoxes.swift; sourceTree = ""; }; BBAA4F00243D8E3B005AAD5F /* RadioBoxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioBoxModel.swift; sourceTree = ""; }; BBAA4F01243D8E3B005AAD5F /* RadioBoxesModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioBoxesModel.swift; sourceTree = ""; }; @@ -692,6 +693,9 @@ D264FAA0243CF66B00D98315 /* ContainerCollectionReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerCollectionReusableView.swift; sourceTree = ""; }; D264FAA2243E632F00D98315 /* ProgrammaticCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgrammaticCollectionViewController.swift; sourceTree = ""; }; D264FAA4243F66A500D98315 /* CollectionTemplateItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionTemplateItemProtocol.swift; sourceTree = ""; }; + D264FAA6243FE13B00D98315 /* RadioBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioBox.swift; sourceTree = ""; }; + D264FAA92440F97600D98315 /* CollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionView.swift; sourceTree = ""; }; + D264FAAB2441009400D98315 /* RadioBoxCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioBoxCollectionViewCell.swift; sourceTree = ""; }; D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = ""; }; D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemModel.swift; sourceTree = ""; }; D274CA322236A78900B01B62 /* FooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterView.swift; sourceTree = ""; }; @@ -1412,6 +1416,13 @@ path = Doughnut; sourceTree = ""; }; + D264FAA8243FE17A00D98315 /* Selectors */ = { + isa = PBXGroup; + children = ( + ); + path = Selectors; + sourceTree = ""; + }; D29DF0C221E404D4003B2FB9 = { isa = PBXGroup; children = ( @@ -1487,6 +1498,7 @@ D29DF10D21E67A70003B2FB9 /* Atoms */ = { isa = PBXGroup; children = ( + D264FAA8243FE17A00D98315 /* Selectors */, D29DF22B21E6A0FA003B2FB9 /* TextFields */, D29DF17D21E69E26003B2FB9 /* Views */, D29DF16821E69E1F003B2FB9 /* Buttons */, @@ -1639,10 +1651,11 @@ D29DF17D21E69E26003B2FB9 /* Views */ = { isa = PBXGroup; children = ( + D264FAAB2441009400D98315 /* RadioBoxCollectionViewCell.swift */, BBAA4F01243D8E3B005AAD5F /* RadioBoxesModel.swift */, BBAA4EFF243D8E3B005AAD5F /* RadioBoxes.swift */, BBAA4F00243D8E3B005AAD5F /* RadioBoxModel.swift */, - BBAA4EFE243D8E3A005AAD5F /* RadioBoxCollectionViewCell.swift */, + D264FAA6243FE13B00D98315 /* RadioBox.swift */, 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */, 01509D922327ECFB00EF99AA /* ProgressBar.swift */, 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */, @@ -1835,6 +1848,7 @@ 0AE14F63238315D2005417F8 /* TextField.swift */, D2755D7A23689C7500485468 /* TableViewCell.swift */, D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */, + D264FAA92440F97600D98315 /* CollectionView.swift */, 0A5D59C323AD488600EFD9E9 /* Protocols */, ); path = BaseClasses; @@ -2044,6 +2058,7 @@ AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */, 94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, + D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */, 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */, AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */, @@ -2122,7 +2137,6 @@ 525239C02407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift in Sources */, D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */, D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */, - BBAA4F02243D8E3B005AAD5F /* RadioBoxCollectionViewCell.swift in Sources */, 8D084AD22410BF7600951227 /* ListOneColumnFullWidthTextBodyText.swift in Sources */, 94C0150C2421564A005811A9 /* ActionCollapseNotificationModel.swift in Sources */, 014AA73123C5059B006F3E93 /* ListPageTemplateModel.swift in Sources */, @@ -2232,6 +2246,7 @@ 526A265E240D200500B0D828 /* ListTwoColumnCompareChanges.swift in Sources */, 8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */, D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */, + D264FAAC2441009400D98315 /* RadioBoxCollectionViewCell.swift in Sources */, BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */, D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */, 012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */, @@ -2375,6 +2390,7 @@ D260106523D0CEA700764D80 /* StackModel.swift in Sources */, 0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */, D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */, + D264FAA7243FE13B00D98315 /* RadioBox.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MVMCoreUI/Atomic/Atoms/Views/RadioBox.swift b/MVMCoreUI/Atomic/Atoms/Views/RadioBox.swift new file mode 100644 index 00000000..616c7fd6 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/RadioBox.swift @@ -0,0 +1,159 @@ +// +// RadioBox.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/9/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class RadioBox: Control { + public let label = Label.createLabelRegularBodySmall(true) + public let subTextLabel = Label.createLabelRegularMicro(true) + public var isOutOfStock = false + public var accentColor = UIColor.mvmRed + + public let innerPadding: CGFloat = 12.0 + + private var borderLayer: CALayer? + private var strikeLayer: CALayer? + private var maskLayer: CALayer? + + public var radioBoxModel: RadioBoxModel? { + return model as? RadioBoxModel + } + + open override func draw(_ layer: CALayer, in ctx: CGContext) { + // Draw the strikethrough + strikeLayer?.removeFromSuperlayer() + if isOutOfStock { + let line = getStrikeThrough(color: .black, thickness: 1) + layer.addSublayer(line) + strikeLayer = line + } + + // Draw the border + borderLayer?.removeFromSuperlayer() + if isSelected { + layer.borderWidth = 0 + let border = getSelectedBorder() + layer.addSublayer(border) + borderLayer = border + } else { + layer.borderWidth = 1 + } + + // Handle Mask + maskLayer?.removeFromSuperlayer() + if !isEnabled { + let mask = getMaskLayer() + layer.mask = mask + } + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + label.updateView(size) + subTextLabel.updateView(size) + layer.setNeedsDisplay() + } + + open override func setupView() { + super.setupView() + + layer.delegate = self + layer.borderColor = UIColor.black.cgColor + layer.borderWidth = 1 + + label.numberOfLines = 1 + addSubview(label) + NSLayoutConstraint.constraintPinSubview(label, pinTop: true, topConstant: innerPadding, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: innerPadding, pinRight: true, rightConstant: innerPadding) + + subTextLabel.textColor = .mvmCoolGray6 + subTextLabel.numberOfLines = 1 + addSubview(subTextLabel) + NSLayoutConstraint.constraintPinSubview(subTextLabel, pinTop: false, topConstant:0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: innerPadding, pinRight: true, rightConstant: innerPadding) + bottomAnchor.constraint(lessThanOrEqualTo: subTextLabel.bottomAnchor, constant: innerPadding).isActive = true + subTextLabel.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 2).isActive = true + + addTarget(self, action: #selector(touched), for: .touchUpInside) + } + + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? RadioBoxModel else { return } + isSelected = model.selected + isEnabled = model.enabled + label.text = model.text + subTextLabel.text = model.subText + isOutOfStock = model.strikethrough + } + + @objc open func touched() { + isSelected = !isSelected + layer.setNeedsDisplay() + } + + /// Gets the selected state border + func getSelectedBorder() -> CAShapeLayer { + let layer = CAShapeLayer() + + let topLineWidth: CGFloat = 4 + let topLinePath = UIBezierPath() + topLinePath.lineWidth = topLineWidth + topLinePath.move(to: CGPoint(x: 0, y: topLineWidth / 2.0)) + topLinePath.addLine(to: CGPoint(x: bounds.width, y: topLineWidth / 2.0)) + + let topLineLayer = CAShapeLayer() + topLineLayer.fillColor = nil + topLineLayer.strokeColor = UIColor.mvmRed.cgColor + topLineLayer.lineWidth = 4 + topLineLayer.path = topLinePath.cgPath + layer.addSublayer(topLineLayer) + + let lineWidth: CGFloat = 1 + let halfLineWidth: CGFloat = 0.5 + let linePath = UIBezierPath() + linePath.move(to: CGPoint(x: halfLineWidth, y: topLineWidth)) + linePath.addLine(to: CGPoint(x: halfLineWidth, y: bounds.height)) + linePath.move(to: CGPoint(x: 0, y: bounds.height - halfLineWidth)) + linePath.addLine(to: CGPoint(x: bounds.width, y: bounds.height - halfLineWidth)) + linePath.move(to: CGPoint(x: bounds.width - halfLineWidth, y: bounds.height)) + linePath.addLine(to: CGPoint(x: bounds.width - halfLineWidth, y: topLineWidth)) + + let borderLayer = CAShapeLayer() + borderLayer.fillColor = nil + borderLayer.strokeColor = UIColor.black.cgColor + borderLayer.lineWidth = lineWidth + borderLayer.path = linePath.cgPath + layer.addSublayer(borderLayer) + + return layer + } + + /// Adds a border to edge + func getStrikeThrough(color: UIColor, thickness: CGFloat) -> CAShapeLayer { + let border = CAShapeLayer() + border.name = "strikethrough" + border.fillColor = nil + border.opacity = 1.0 + border.lineWidth = thickness + border.strokeColor = color.cgColor + + let linePath = UIBezierPath() + linePath.move(to: CGPoint(x: 0, y: bounds.height)) + linePath.addLine(to: CGPoint(x: bounds.width, y: 0)) + border.path = linePath.cgPath + return border + } + + func getMaskLayer() -> CALayer { + let mask = CALayer() + mask.backgroundColor = UIColor.white.cgColor + mask.opacity = 0.3 + mask.frame = bounds + return mask + } +} + diff --git a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxCollectionViewCell.swift b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxCollectionViewCell.swift index 419f278c..c90b5e92 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxCollectionViewCell.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxCollectionViewCell.swift @@ -7,164 +7,17 @@ // import Foundation -open class RadioBoxCollectionViewCell: UICollectionViewCell, MoleculeViewProtocol { +open class RadioBoxCollectionViewCell: CollectionViewCell { + let radioBox = RadioBox() - public let bodyLabel = Label(frame: .zero) - public let subTextLabel = Label(frame: .zero) - public let lineView = View(frame: .zero) - var bottomView = MVMCoreUICommonViewsUtility.commonView() - public var lineViewHeight: NSLayoutConstraint? - public var fieldValue: String? - var boxModel: RadioBoxModel! - - open override var isSelected: Bool{ - didSet{ - if let shapeLayer = self.bottomView.layer.sublayers?.filter({$0.name == "outofstock"}).first as? CAShapeLayer { - shapeLayer.strokeColor = isSelected ? UIColor.black.cgColor : UIColor.mfGet(forHex: "#747676").cgColor - } - self.lineViewHeight?.constant = self.isSelected ? 4.0 : 0 - self.bottomView.layer.sublayers?.filter({$0.name == "border"}).forEach({$0.removeFromSuperlayer()}) - if(self.isSelected){ - self.bottomView.layer.addBorder(edge: .bottom, color: UIColor.mfGet(forHex: "#0000"), thickness: 1.0) - self.bottomView.layer.addBorder(edge: .left, color: UIColor.mfGet(forHex: "#0000"), thickness: 1.0) - self.bottomView.layer.addBorder(edge: .right, color: UIColor.mfGet(forHex: "#0000"), thickness: 1.0) - } - else { - self.addBordertoView("#747676") - } - UIView.animate(withDuration: 0.5) { - self.layoutIfNeeded() - } - } + open override func setupView() { + super.setupView() + addMolecule(radioBox) + MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0) } - var isOutOfStock: Bool = false { - didSet{ - DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - self.bottomView.layer.sublayers?.filter({$0.name == "outofstock"}).forEach({$0.removeFromSuperlayer()}) - if(self.isOutOfStock) { - self.addOutOfStockLine() - } - } - } - } - - public override init(frame: CGRect) { - super.init(frame: .zero) - setupView() - } - - public required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - setupView() - } - - public func setupView() { - guard bottomView.superview == nil else { - return - } - isAccessibilityElement = false - contentView.isAccessibilityElement = false - insetsLayoutMarginsFromSafeArea = false - contentView.insetsLayoutMarginsFromSafeArea = false - contentView.preservesSuperviewLayoutMargins = false - bottomView.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(bottomView) - NSLayoutConstraint.constraintPinSubview(toSuperview: bottomView) - - bottomView.addSubview(lineView) - NSLayoutConstraint.constraintPinSubview(lineView, pinTop: true, pinBottom: false, pinLeft: true, pinRight: true) - lineViewHeight = lineView.heightAnchor.constraint(equalToConstant: 0) - lineViewHeight?.isActive = true - - bodyLabel.numberOfLines = 1 - bottomView.addSubview(bodyLabel) - NSLayoutConstraint.constraintPinSubview(bodyLabel, pinTop: false, topConstant:0 , pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 12, pinRight: true, rightConstant: 12) - bodyLabel.topAnchor.constraint(equalTo: lineView.bottomAnchor, constant: 12).isActive = true - - subTextLabel.numberOfLines = 1 - bottomView.addSubview(subTextLabel) - NSLayoutConstraint.constraintPinSubview(subTextLabel, pinTop: false, topConstant:0 , pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 12, pinRight: true, rightConstant: 12) - subTextLabel.bottomAnchor.constraint(lessThanOrEqualTo: bottomView.bottomAnchor, constant: -12.0).isActive = true - subTextLabel.topAnchor.constraint(equalTo: bodyLabel.bottomAnchor, constant: 2).isActive = true - - subTextLabel.font = MFFonts.mfFontTXRegular(11.0) - bodyLabel.font = MFFonts.mfFontTXRegular(13.0) - subTextLabel.textColor = UIColor.mfGet(forHex: "#747676") - - - } - - public func updateView(_ size: CGFloat) { - self.setNeedsLayout() - self.bottomView.setNeedsLayout() - self.bottomView.layer.sublayers?.filter({$0.name == "border"}).forEach({$0.removeFromSuperlayer()}) - DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - self.addBordertoView(self.boxModel.enabled ? "#747676" : "#D8DADA") - } - } - - private func addBordertoView(_ color:String){ - bottomView.layer.addBorder(edge: .bottom, color: UIColor.mfGet(forHex: color), thickness: 1.0) - bottomView.layer.addBorder(edge: .left, color: UIColor.mfGet(forHex: color), thickness: 1.0) - bottomView.layer.addBorder(edge: .right, color: UIColor.mfGet(forHex: color), thickness: 1.0) - bottomView.layer.addBorder(edge: .top, color: UIColor.mfGet(forHex: color), thickness: 1.0) - } - - private func addOutOfStockLine(){ - let path = UIBezierPath() - path.move(to: CGPoint(x: 0, y: bottomView.bounds.height)) - path.addLine(to: CGPoint(x: bottomView.bounds.width, y: 0)) - let shapeLayer = CAShapeLayer() - shapeLayer.name = "outofstock" - shapeLayer.path = path.cgPath - shapeLayer.strokeColor = self.boxModel.enabled ? UIColor.black.cgColor : UIColor.mfGet(forHex: "#D8DADA").cgColor - shapeLayer.lineWidth = 0.5 - bottomView.layer.addSublayer(shapeLayer) - } - - public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let collectionModel = model as? RadioBoxModel else { return } - boxModel = collectionModel - if let backgroundColor = collectionModel.backgroundColor { - bottomView.backgroundColor = backgroundColor.uiColor - } - self.isUserInteractionEnabled = collectionModel.enabled - lineView.backgroundColor = collectionModel.selectedAccentColor?.uiColor - bodyLabel.text = collectionModel.text - subTextLabel.text = collectionModel.subText - fieldValue = collectionModel.fieldValue - isOutOfStock = collectionModel.strikethrough - - } -} - -extension CALayer { - - func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) { - - let border = CALayer() - border.name = "border" - switch edge { - case UIRectEdge.top: - border.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: thickness) - break - case UIRectEdge.bottom: - border.frame = CGRect(x: 0, y: self.frame.height - thickness, width: self.frame.width, height: thickness) - break - case UIRectEdge.left: - border.frame = CGRect(x: 0, y: 0, width: thickness, height: self.frame.height) - break - case UIRectEdge.right: - border.frame = CGRect(x: self.frame.width - thickness, y: 0, width: thickness, height: self.frame.height) - break - default: - break - } - - border.backgroundColor = color.cgColor; - self.addSublayer(border) + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let model = model as? RadioBoxModel else { return } + radioBox.set(with: model, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxModel.swift index 0c119ed8..89bdc842 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxModel.swift @@ -12,7 +12,7 @@ import Foundation public var text: String public var subText: String? public var backgroundColor: Color? = Color(uiColor: .white) - public var selectedAccentColor: Color? = try? Color(colorString: "#D52B1E") + public var selectedAccentColor = Color(uiColor: .mvmRed) public var selected: Bool = false public var enabled: Bool = true public var strikethrough: Bool = false @@ -32,7 +32,6 @@ import Foundation case fieldValue case fieldKey case groupName - } required public init(from decoder: Decoder) throws { @@ -57,7 +56,6 @@ import Foundation fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) - } public func encode(to encoder: Encoder) throws { @@ -65,14 +63,13 @@ import Foundation try container.encode(moleculeName, forKey: .moleculeName) try container.encode(text, forKey: .text) try container.encodeIfPresent(subText, forKey: .subText) - try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor) + try container.encode(selectedAccentColor, forKey: .selectedAccentColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encodeIfPresent(selected, forKey: .selected) - try container.encodeIfPresent(enabled, forKey: .enabled) - try container.encodeIfPresent(strikethrough, forKey: .strikethrough) + try container.encode(selected, forKey: .selected) + try container.encode(enabled, forKey: .enabled) + try container.encode(strikethrough, forKey: .strikethrough) try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(groupName, forKey: .groupName) - } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxes.swift b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxes.swift index d0cae6b4..58090598 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxes.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxes.swift @@ -10,10 +10,10 @@ import Foundation open class RadioBoxes: View { - public let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) + public let collectionView = CollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) /// The models for the molecules. - var boxes: [RadioBoxModel]? + public var boxes: [RadioBoxModel]? public var collectionViewHeight: NSLayoutConstraint? private let boxWidth: Double = 151.0 private let boxHeight: Double = 64.0 @@ -30,15 +30,8 @@ open class RadioBoxes: View { // MARK: - MVMCoreViewProtocol open override func setupView() { super.setupView() - guard collectionView.superview == nil else { - return - } - collectionView.translatesAutoresizingMaskIntoConstraints = false collectionView.dataSource = self collectionView.delegate = self - collectionView.showsHorizontalScrollIndicator = false - collectionView.backgroundColor = .clear - collectionView.isAccessibilityElement = false addSubview(collectionView) NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView) collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 300) diff --git a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxesModel.swift index d50978a1..653eae13 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/RadioBoxesModel.swift @@ -9,33 +9,37 @@ import Foundation @objcMembers public class RadioBoxesModel: MoleculeModelProtocol { public static var identifier: String = "radioBoxes" - public var backgroundColor: Color? = Color(uiColor: .white) - public var selectedAccentColor: Color? = Color(uiColor: .red) + public var backgroundColor: Color? + public var selectedAccentColor: Color? public var boxes: [RadioBoxModel] + public var fieldKey: String? + public var groupName: String? private enum CodingKeys: String, CodingKey { case moleculeName case selectedAccentColor case backgroundColor case boxes - + case fieldKey + case groupName } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) { - selectedAccentColor = color - } - if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) { - backgroundColor = color - } + selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) boxes = try typeContainer.decode([RadioBoxModel].self, forKey: .boxes) + fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(boxes, forKey: .boxes) try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(fieldKey, forKey: .fieldKey) + try container.encodeIfPresent(groupName, forKey: .groupName) } } diff --git a/MVMCoreUI/Atomic/Organisms/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel.swift index 1ed2ecd2..e900dda8 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel.swift @@ -83,12 +83,8 @@ open class Carousel: View { // MARK: - MVMCoreViewProtocol open override func setupView() { super.setupView() - collectionView.translatesAutoresizingMaskIntoConstraints = false collectionView.dataSource = self collectionView.delegate = self - collectionView.showsHorizontalScrollIndicator = false - collectionView.backgroundColor = .clear - collectionView.isAccessibilityElement = false addSubview(collectionView) bottomPin = NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)?[ConstraintBot] as? NSLayoutConstraint diff --git a/MVMCoreUI/BaseClasses/CollectionView.swift b/MVMCoreUI/BaseClasses/CollectionView.swift new file mode 100644 index 00000000..ff572a2e --- /dev/null +++ b/MVMCoreUI/BaseClasses/CollectionView.swift @@ -0,0 +1,46 @@ +// +// CollectionView.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/10/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class CollectionView: UICollectionView, MVMCoreViewProtocol { + + private var initialSetupPerformed = false + + private func initialSetup() { + if !initialSetupPerformed { + initialSetupPerformed = true + setupView() + } + } + + public override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) { + super.init(frame: frame, collectionViewLayout: layout) + initialSetup() + } + + required public init?(coder: NSCoder) { + super.init(coder: coder) + initialSetup() + } + + public func updateView(_ size: CGFloat) { + for cell in visibleCells { + (cell as? MVMCoreViewProtocol)?.updateView(size) + } + collectionViewLayout.invalidateLayout() + } + + public func setupView() { + translatesAutoresizingMaskIntoConstraints = false + showsHorizontalScrollIndicator = false + backgroundColor = .clear + isAccessibilityElement = false + contentInsetAdjustmentBehavior = .always + } +} diff --git a/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift b/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift index 9d279d79..5e7b87b0 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift +++ b/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift @@ -46,14 +46,9 @@ import Foundation /// Creates the collection view. open func createCollectionView() -> UICollectionView { - let collection = UICollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout()) - collection.translatesAutoresizingMaskIntoConstraints = false + let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout()) collection.dataSource = self collection.delegate = self - collection.showsHorizontalScrollIndicator = false - collection.backgroundColor = .white - collection.isAccessibilityElement = false - collection.contentInsetAdjustmentBehavior = .always return collection }