diff --git a/MVMCoreUI/Atomic/Atoms/Views/Star.swift b/MVMCoreUI/Atomic/Atoms/Views/Star.swift index 7f12d6f4..87e81a72 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Star.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Star.swift @@ -18,15 +18,28 @@ import Foundation public var starModel: StarModel? { return model as? StarModel } - public var progressBar = UIProgressView(progressViewStyle: .bar) - public var percent: Int = 0 + @Percent public var percent = 0 { + didSet { + updateAccessibilityLabel() + setNeedsDisplay() + } + } public var size: CGFloat = 30 { didSet { widthConstraint?.constant = size setNeedsDisplay() } } - public var borderColor: Color = Color(uiColor: .mvmBlack) + public var fillColor = UIColor.mvmBlack { + didSet { + setNeedsDisplay() + } + } + public var borderColor: CGColor = UIColor.mvmBlack.cgColor { + didSet { + setNeedsDisplay() + } + } //-------------------------------------------------- // MARK: - Constraints @@ -38,7 +51,14 @@ import Foundation // MARK: - State Handling //------------------------------------------------------ open override func draw(_ rect: CGRect) { - //Draw the heart + //Draw progress + let width = bounds.size.width * percent / 100.0 + let progressRect = CGRect(x: 0, y: 0, width: width, height: bounds.height) + fillColor.set() + guard let context = UIGraphicsGetCurrentContext() else { return } + context.fill(progressRect) + + //Draw the star starLayer?.removeFromSuperlayer() let star = drawStar() layer.addSublayer(star) @@ -84,18 +104,40 @@ import Foundation shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.opacity = 1.0 shapeLayer.lineWidth = 1 - shapeLayer.strokeColor = borderColor.cgColor + shapeLayer.strokeColor = borderColor return shapeLayer } - + //-------------------------------------------------- - // MARK: - Lifecycle + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + open override func reset() { + super.reset() + borderColor = UIColor.mvmBlack.cgColor + fillColor = .mvmBlack + percent = 0 + } + + 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 } + percent = model.percent + if let fillColor = model.fillColor?.uiColor { + self.fillColor = fillColor + } + if let borderColor = model.borderColor?.cgColor { + self.borderColor = borderColor + } + size = model.size + updateAccessibilityLabel() + } + + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol //-------------------------------------------------- open override func setupView() { super.setupView() - progressBar.translatesAutoresizingMaskIntoConstraints = false - addSubview(progressBar) - NSLayoutConstraint.constraintPinSubview(toSuperview: progressBar) + backgroundColor = .clear widthConstraint = widthAnchor.constraint(equalToConstant: 30) widthConstraint?.isActive = true heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1) @@ -104,23 +146,9 @@ import Foundation updateAccessibilityLabel() } - 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 } - progressBar.progress = Float((model.percent) / 100.0) - percent = Int(model.percent) - progressBar.progressTintColor = (model.fillColor != nil) ? model.fillColor?.uiColor : .mvmBlack - progressBar.trackTintColor = .mvmWhite - if let border = model.borderColor { - borderColor = border - } - size = model.size - updateAccessibilityLabel() - } - // MARK: - Accessibility func updateAccessibilityLabel() { accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "star") - accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "star_percent") ?? "", percent) + accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "star_percent") ?? "", Int(percent)) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/Stars.swift b/MVMCoreUI/Atomic/Atoms/Views/Stars.swift index 742dc580..07a78e95 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Stars.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Stars.swift @@ -13,7 +13,6 @@ open class Stars: View { // MARK: - Properties //-------------------------------------------------- private var stack = UIStackView() - public var starElements = [Star]() public var starsModel: StarsModel? { return model as? StarsModel } @@ -23,20 +22,17 @@ open class Stars: View { private var starsFilledValue: Float = 0 //-------------------------------------------------- - // MARK: - Lifecycle + // MARK: - MVMCoreViewProtocol //-------------------------------------------------- open override func setupView() { super.setupView() stack.translatesAutoresizingMaskIntoConstraints = false - addSubview(stack) - NSLayoutConstraint.constraintPinSubview(toSuperview: stack) - let leading = stack.leadingAnchor.constraint(equalTo: self.leadingAnchor) - leading.priority = UILayoutPriority(rawValue: 1000) - leading.isActive = true - heightConstraint = heightAnchor.constraint(equalToConstant: 30) - heightConstraint?.isActive = true stack.axis = .horizontal stack.spacing = itemSpacing + addSubview(stack) + NSLayoutConstraint.constraintPinSubview(toSuperview: stack) + heightConstraint = heightAnchor.constraint(equalToConstant: 30) + heightConstraint?.isActive = true isAccessibilityElement = true updateAccessibilityLabel() } @@ -46,70 +42,69 @@ open class Stars: View { stack.updateView(size) } + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) self.delegateObject = delegateObject - createStar() - updateStar() + createStars() + updateStars() updateAccessibilityLabel() } + public override func reset() { + stack.subviews.forEach({$0.removeFromSuperview()}) + super.reset() + } + //------------------------------------------------------ // MARK: - Methods //------------------------------------------------------ - func createStar() { - if let starsModel = starsModel { - for starModel in starsModel.stars { - let star = Star() - star.set(with: starModel, delegateObject, nil) - stack.addArrangedSubview(star) - starElements.append(star) - star.isAccessibilityElement = false - //Star model colors should take priority over stars. - if let borderColor = starsModel.borderColor, starModel.borderColor == nil { - star.borderColor = borderColor - } - if let fillColor = starsModel.fillColor, starModel.fillColor == nil { - star.progressBar.progressTintColor = fillColor.uiColor - } - if let backgroundColor = starsModel.starBackgroundColor, starModel.backgroundColor == nil { - star.backgroundColor = backgroundColor.uiColor - } - } - heightConstraint?.constant = starsModel.size + func createStars() { + guard let starsModel = starsModel else { return } + for starModel in starsModel.stars { + let star = Star(model: starModel, delegateObject, nil) + star.isAccessibilityElement = false + stack.addArrangedSubview(star) } + heightConstraint?.constant = starsModel.size } - //Update star progress and size with starsModel values - func updateStar() { - if let starsModel = starsModel { - let percentRequiredToFillStarFully = CGFloat(100/(starElements.count)) - let numberOfFilledStars = Int(starsModel.percent/percentRequiredToFillStarFully) - starsFilledValue = Float(numberOfFilledStars) - for (index, star) in starElements.enumerated() { - //Fill the stars based on percentage. Ex: if there were 4 stars, 75 percent is 3 full stars - if index < numberOfFilledStars { - star.progressBar.progress = 1 - } else if index == numberOfFilledStars { - let remainingProgress = (starsModel.percent).truncatingRemainder(dividingBy: percentRequiredToFillStarFully) - let fillPercent = remainingProgress/percentRequiredToFillStarFully - starsFilledValue += Float(fillPercent) - star.progressBar.progress = Float(fillPercent) - } else { - star.progressBar.progress = 0 - } - star.size = starsModel.size + func updateStars() { + guard let starsModel = starsModel else { return } + let percentRequiredToFillStarFully = CGFloat(100/(stack.arrangedSubviews.count)) + let numberOfFilledStars = Int(starsModel.percent/percentRequiredToFillStarFully) + starsFilledValue = Float(numberOfFilledStars) + for case let (index, star as Star) in stack.arrangedSubviews.enumerated() { + //Star model colors should take priority over stars. + if let borderColor = starsModel.borderColor?.cgColor, star.starModel?.borderColor == nil { + star.borderColor = borderColor } + if let fillColor = starsModel.fillColor?.uiColor, star.starModel?.fillColor == nil { + star.fillColor = fillColor + } + if let backgroundColor = starsModel.starBackgroundColor?.uiColor, star.starModel?.backgroundColor == nil { + star.backgroundColor = backgroundColor + } + + //Fill the stars based on percentage. Ex: if there were 4 stars, 75 percent is 3 full stars + if index < numberOfFilledStars { + star.percent = 100 + } else if index == numberOfFilledStars { + let remainingProgress = (starsModel.percent).truncatingRemainder(dividingBy: percentRequiredToFillStarFully) + let fillPercent = remainingProgress/percentRequiredToFillStarFully + starsFilledValue += Float(fillPercent) + star.percent = fillPercent * 100 + } else { + star.percent = 0 + } + star.size = starsModel.size } } - public override func reset() { - super.reset() - stack.subviews.forEach({$0.removeFromSuperview()}) - } - // MARK: - Accessibility func updateAccessibilityLabel() { - accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "stars_filled") ?? "", starsFilledValue, starElements.count) + accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "stars_filled") ?? "", starsFilledValue, stack.arrangedSubviews.count) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift b/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift index ad52b18e..27515a64 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift @@ -47,12 +47,8 @@ import Foundation if let percent = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .percent) { self.percent = percent } - if let borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) { - self.borderColor = borderColor - } - if let fillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) { - self.fillColor = fillColor - } + borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) + fillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) if let size = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .size) { self.size = size }