diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 2cee3c22..07b1b263 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -235,7 +235,6 @@ AA71AD4024A32FE700ACA76F /* HeadersH2Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA71AD3F24A32FE700ACA76F /* HeadersH2Link.swift */; }; AA7F32AB246C0F7900C965BA /* ListLeftVariableRadioButtonAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7F32AA246C0F7900C965BA /* ListLeftVariableRadioButtonAllTextAndLinksModel.swift */; }; AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7F32AC246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift */; }; - AA817FE6251C71B600EF0C6C /* StarCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA817FE5251C71B600EF0C6C /* StarCollectionViewCell.swift */; }; AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; }; AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA99724F2475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift */; }; AA997252247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA997251247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift */; }; @@ -733,7 +732,6 @@ AA71AD3F24A32FE700ACA76F /* HeadersH2Link.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2Link.swift; sourceTree = ""; }; AA7F32AA246C0F7900C965BA /* ListLeftVariableRadioButtonAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAllTextAndLinksModel.swift; sourceTree = ""; }; AA7F32AC246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAllTextAndLinks.swift; sourceTree = ""; }; - AA817FE5251C71B600EF0C6C /* StarCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StarCollectionViewCell.swift; sourceTree = ""; }; AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = ""; }; AA99724F2475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconAllTextLinksModel.swift; sourceTree = ""; }; AA997251247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconAllTextLinks.swift; sourceTree = ""; }; @@ -1900,7 +1898,6 @@ AA37CBD42519072F0027344C /* Stars.swift */, AA07EA902510A442009A2AE3 /* StarModel.swift */, AA07EA922510A451009A2AE3 /* Star.swift */, - AA817FE5251C71B600EF0C6C /* StarCollectionViewCell.swift */, ); path = Views; sourceTree = ""; @@ -2240,7 +2237,6 @@ AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */, 324FB6AA249366F3002552C7 /* ListLeftVariableNumberedListBodyTextModel.swift in Sources */, 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */, - AA817FE6251C71B600EF0C6C /* StarCollectionViewCell.swift in Sources */, AA0A257824766C8A00862F64 /* ListLeftVariableIconWithRightCaretBodyTextModel.swift in Sources */, 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */, 8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/Star.swift b/MVMCoreUI/Atomic/Atoms/Views/Star.swift index 50639dc3..2c532f46 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Star.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Star.swift @@ -15,7 +15,9 @@ import Foundation //-------------------------------------------------- private var starLayer: CAShapeLayer? private let maskLayer = CAShapeLayer() - public var starModel: StarModel? + public var starModel: StarModel? { + return model as? StarModel + } public var progressBar = UIProgressView(progressViewStyle: .bar) //-------------------------------------------------- @@ -37,12 +39,12 @@ import Foundation //Mask the star maskLayer.removeFromSuperlayer() maskLayer.path = star.path - self.layer.mask = maskLayer + layer.mask = maskLayer } func drawStar() -> CAShapeLayer { let shapeLayer = CAShapeLayer() - shapeLayer.frame = self.bounds + shapeLayer.frame = bounds let starPath = UIBezierPath() let center = shapeLayer.position let theta = .pi / CGFloat(5.0) @@ -86,12 +88,15 @@ import Foundation progressBar.translatesAutoresizingMaskIntoConstraints = false addSubview(progressBar) NSLayoutConstraint.constraintPinSubview(toSuperview: progressBar) + widthConstraint = widthAnchor.constraint(equalToConstant: 30) + widthConstraint?.isActive = true + heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1) + heightConstraint?.isActive = true } public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? StarModel else { return } - self.starModel = model progressBar.progress = Float((model.percent) / 100.0) progressBar.progressTintColor = model.fillColor.uiColor progressBar.trackTintColor = .mvmWhite @@ -100,10 +105,7 @@ import Foundation func setFrame(with size: CGFloat) { progressBar.frame = CGRect(x: 0, y: 0, width: size, height: size) - widthConstraint = widthAnchor.constraint(equalToConstant: size) - widthConstraint?.isActive = true - heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1) - heightConstraint?.isActive = true + widthConstraint?.constant = size setNeedsDisplay() } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/StarCollectionViewCell.swift b/MVMCoreUI/Atomic/Atoms/Views/StarCollectionViewCell.swift deleted file mode 100644 index 08774d45..00000000 --- a/MVMCoreUI/Atomic/Atoms/Views/StarCollectionViewCell.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// StarCollectionViewCell.swift -// MVMCoreUI -// -// Created by Lekshmi S on 24/09/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -open class StarCollectionViewCell: CollectionViewCell { - public let star = Star() - - open override func setupView() { - super.setupView() - addMolecule(star) - MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0) - } - - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let model = model as? StarModel else { return } - star.set(with: model, delegateObject, additionalData) - } -} diff --git a/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift b/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift index 402ada9a..1d473b86 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift @@ -57,9 +57,9 @@ open class StarModel: MoleculeModelProtocol { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(percent, forKey: .percent) - try container.encodeIfPresent(borderColor, forKey: .borderColor) - try container.encodeIfPresent(fillColor, forKey: .fillColor) - try container.encodeIfPresent(size, forKey: .size) + try container.encode(percent, forKey: .percent) + try container.encode(borderColor, forKey: .borderColor) + try container.encode(fillColor, forKey: .fillColor) + try container.encode(size, forKey: .size) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/Stars.swift b/MVMCoreUI/Atomic/Atoms/Views/Stars.swift index 41f80bc0..d7dba177 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Stars.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Stars.swift @@ -12,144 +12,71 @@ open class Stars: View { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public var collectionView: CollectionView! - public var stars: [StarModel]? - private var size: CGFloat? + private var stack = UIStackView() + public var starsModel: StarsModel? { + return model as? StarsModel + } private var delegateObject: MVMCoreUIDelegateObject? - private var starBackgroundColor: Color? - private var borderColor: Color? - private var fillColor: Color? - private var progress: CGFloat? - private var cellSize: CGFloat = 30.0 - - //------------------------------------------------------ - // MARK: - Constraints - //------------------------------------------------------ - public var collectionViewHeight: NSLayoutConstraint? private let itemSpacing: CGFloat = 3.0 //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- - open override func layoutSubviews() { - super.layoutSubviews() - // Accounts for any collection size changes - setHeight() - DispatchQueue.main.async { - self.collectionView.collectionViewLayout.invalidateLayout() - } - } - open override func setupView() { super.setupView() - collectionView = createCollectionView() - addSubview(collectionView) - NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView) - collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 30) - collectionViewHeight?.isActive = true + stack.translatesAutoresizingMaskIntoConstraints = false + addSubview(stack) + stack.topAnchor.constraint(equalTo: topAnchor).isActive = true + bottomAnchor.constraint(equalTo: stack.bottomAnchor).isActive = true + stack.axis = .horizontal + stack.spacing = itemSpacing } @objc override open func updateView(_ size: CGFloat) { super.updateView(size) - self.size = size - collectionView.updateView(size) + stack.updateView(size) } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) self.delegateObject = delegateObject - - guard let starsModel = model as? StarsModel else { return } - stars = starsModel.stars - cellSize = starsModel.size - starBackgroundColor = starsModel.starBackgroundColor ?? Color(uiColor: .clear) - borderColor = starsModel.borderColor - fillColor = starsModel.fillColor - progress = starsModel.percent - collectionView.reloadData() + createStar() } //------------------------------------------------------ // MARK: - Methods //------------------------------------------------------ - /// Creates the collection view. - open func createCollectionView() -> CollectionView { - let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout()) - collection.dataSource = self - collection.delegate = self - collection.register(StarCollectionViewCell.self, forCellWithReuseIdentifier: "StarCollectionViewCell") - return collection - } - - /// Creates the layout for the collection. - open func createCollectionViewLayout() -> UICollectionViewLayout { - let layout = UICollectionViewFlowLayout() - layout.scrollDirection = .vertical - layout.minimumLineSpacing = itemSpacing - layout.minimumInteritemSpacing = itemSpacing - return layout - } - - open func setHeight() { - guard let stars = stars, stars.count > 0 else { - collectionViewHeight?.constant = 0 - return - } - // Calculate the height - let starsInRow = floor(CGFloat(collectionView.bounds.width/(cellSize + itemSpacing))) - let numberOfRows = ceil(CGFloat(stars.count)/starsInRow) - let height = (numberOfRows * cellSize) + (itemSpacing * (numberOfRows-1)) - - if let oldHeight = collectionViewHeight?.constant, - height != oldHeight { - // Notify delegate of height change, called async to avoid various race conditions caused while happening while laying out initially. - DispatchQueue.main.async { - self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) + func createStar() { + if let starsModel = starsModel { + stack.subviews.forEach({$0.removeFromSuperview()}) + let stars = starsModel.stars + for (index, starModel) in stars.enumerated() { + let star = Star() + + //Fill the stars based on percentage. Ex: if there were 4 stars, 75 percent is 3 full stars + let percentRequiredToFillStarFully = CGFloat(100/(starsModel.stars.count)) + let numberOfFilledStars = Int(starsModel.percent/percentRequiredToFillStarFully) + if index < numberOfFilledStars { + starModel.percent = 100 + } else if index == numberOfFilledStars { + let remainingProgress = (starsModel.percent).truncatingRemainder(dividingBy: percentRequiredToFillStarFully) + let fillPercent = (remainingProgress/percentRequiredToFillStarFully) * 100 + starModel.percent = fillPercent + } else { + starModel.percent = 0 + } + + starModel.backgroundColor = starsModel.starBackgroundColor + if let borderColor = starsModel.borderColor { + starModel.borderColor = borderColor + } + if let fillColor = starsModel.fillColor { + starModel.fillColor = fillColor + } + starModel.size = starsModel.size + star.set(with: starModel, delegateObject, nil) + stack.addArrangedSubview(star) } } - collectionViewHeight?.constant = CGFloat(height) - } -} - -//------------------------------------------------------ -// MARK: - Delegate methods -//------------------------------------------------------ -extension Stars: UICollectionViewDelegateFlowLayout { - open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return CGSize(width: cellSize, height: cellSize) - } -} - -extension Stars: UICollectionViewDataSource { - open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return stars?.count ?? 0 - } - - open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let molecule = stars?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "StarCollectionViewCell", for: indexPath) as? StarCollectionViewCell else { - fatalError() - } - cell.reset() - - //Fill the stars based on percentage. Ex: if there were 4 stars, 75 percent is 3 full stars - let percentRequiredToFillStarFully = CGFloat(100/(stars?.count ?? 1)) - let numberOfFilledStars = Int((progress ?? 0)/percentRequiredToFillStarFully) - if indexPath.row < numberOfFilledStars { - molecule.percent = 100 - } else if indexPath.row == numberOfFilledStars { - let remainingProgress = (progress ?? 0).truncatingRemainder(dividingBy: percentRequiredToFillStarFully) - let fillPercent = (remainingProgress/percentRequiredToFillStarFully) * 100 - molecule.percent = fillPercent - } else { - molecule.percent = 0 - } - molecule.backgroundColor = starBackgroundColor - molecule.borderColor = borderColor ?? Color(uiColor: .mvmBlack) - molecule.fillColor = fillColor ?? Color(uiColor: .mvmBlack) - molecule.size = cellSize - cell.set(with: molecule, delegateObject, nil) - cell.updateView(size ?? collectionView.bounds.width) - cell.layoutIfNeeded() - return cell } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift b/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift index ef94c4b8..ad52b18e 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift @@ -18,8 +18,8 @@ import Foundation public var starBackgroundColor: Color? public var stars: [StarModel] @Percent public var percent: CGFloat = 0 - public var borderColor: Color = Color(uiColor: .mvmBlack) - public var fillColor: Color = Color(uiColor: .mvmBlack) + public var borderColor: Color? + public var fillColor: Color? public var size: CGFloat = 30.0 //-------------------------------------------------- @@ -64,9 +64,9 @@ import Foundation try container.encode(stars, forKey: .stars) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(starBackgroundColor, forKey: .starBackgroundColor) - try container.encodeIfPresent(percent, forKey: .percent) try container.encodeIfPresent(borderColor, forKey: .borderColor) try container.encodeIfPresent(fillColor, forKey: .fillColor) - try container.encodeIfPresent(size, forKey: .size) + try container.encode(percent, forKey: .percent) + try container.encode(size, forKey: .size) } }