From 3ae3f5a50af64193bf97a811ebb297c8e30e8509 Mon Sep 17 00:00:00 2001 From: Ilya Grechuhin Date: Mon, 11 Sep 2017 15:53:48 +0300 Subject: [PATCH] [rating_view] [ios] Added rating summary view. --- .../RatingSummaryView/RatingSummaryView.swift | 326 ++++++++++++++++++ .../RatingSummaryViewSettings.swift | 45 +++ .../Components/RatingView/RatingView.swift | 33 +- .../RatingView/RatingViewSettings.swift | 78 ++--- iphone/Maps/Maps.xcodeproj/project.pbxproj | 48 ++- 5 files changed, 463 insertions(+), 67 deletions(-) create mode 100644 iphone/Maps/Classes/Components/RatingSummaryView/RatingSummaryView.swift create mode 100644 iphone/Maps/Classes/Components/RatingSummaryView/RatingSummaryViewSettings.swift diff --git a/iphone/Maps/Classes/Components/RatingSummaryView/RatingSummaryView.swift b/iphone/Maps/Classes/Components/RatingSummaryView/RatingSummaryView.swift new file mode 100644 index 0000000000..d2f07f377e --- /dev/null +++ b/iphone/Maps/Classes/Components/RatingSummaryView/RatingSummaryView.swift @@ -0,0 +1,326 @@ +import UIKit + +@IBDesignable final class RatingSummaryView: UIView { + @IBInspectable var value: CGFloat = RatingSummaryViewSettings.Default.value { + didSet { + guard oldValue != value else { return } + let clamped = min(CGFloat(settings.maxValue), max(0, value)) + if clamped == value { + update() + } else { + value = clamped + } + } + } + + @IBInspectable var maxValue: CGFloat { + get { return settings.maxValue } + set { + let clamped = max(0, newValue) + settings.maxValue = clamped + value = min(CGFloat(clamped), max(0, value)) + update() + } + } + + @IBInspectable var topOffset: CGFloat { + get { return settings.topOffset } + set { + settings.topOffset = newValue + update() + } + } + + @IBInspectable var bottomOffset: CGFloat { + get { return settings.bottomOffset } + set { + settings.bottomOffset = newValue + update() + } + } + + @IBInspectable var leadingImageOffset: CGFloat { + get { return settings.leadingImageOffset } + set { + settings.leadingImageOffset = newValue + update() + } + } + + @IBInspectable var margin: CGFloat { + get { return settings.margin } + set { + settings.margin = newValue + update() + } + } + + @IBInspectable var trailingTextOffset: CGFloat { + get { return settings.trailingTextOffset } + set { + settings.trailingTextOffset = newValue + update() + } + } + + var textFont: UIFont { + get { return settings.textFont } + set { + settings.textFont = newValue + update() + } + } + + @IBInspectable var textSize: CGFloat { + get { return settings.textSize } + set { + settings.textSize = newValue + update() + } + } + + @IBInspectable var backgroundOpacity: CGFloat { + get { return settings.backgroundOpacity } + set { + settings.backgroundOpacity = newValue + update() + } + } + + @IBInspectable var horribleImage: UIImage? { + get { return settings.images[.horrible] } + set { + settings.images[.horrible] = newValue + update() + } + } + + @IBInspectable var horribleColor: UIColor? { + get { return settings.colors[.horrible] } + set { + settings.colors[.horrible] = newValue + update() + } + } + + @IBInspectable var badImage: UIImage? { + get { return settings.images[.bad] } + set { + settings.images[.bad] = newValue + update() + } + } + + @IBInspectable var badColor: UIColor? { + get { return settings.colors[.bad] } + set { + settings.colors[.bad] = newValue + update() + } + } + + @IBInspectable var normalImage: UIImage? { + get { return settings.images[.normal] } + set { + settings.images[.normal] = newValue + update() + } + } + + @IBInspectable var normalColor: UIColor? { + get { return settings.colors[.normal] } + set { + settings.colors[.normal] = newValue + update() + } + } + + @IBInspectable var goodImage: UIImage? { + get { return settings.images[.good] } + set { + settings.images[.good] = newValue + update() + } + } + + @IBInspectable var goodColor: UIColor? { + get { return settings.colors[.good] } + set { + settings.colors[.good] = newValue + update() + } + } + + @IBInspectable var excellentImage: UIImage? { + get { return settings.images[.excellent] } + set { + settings.images[.excellent] = newValue + update() + } + } + + @IBInspectable var excellentColor: UIColor? { + get { return settings.colors[.excellent] } + set { + settings.colors[.excellent] = newValue + update() + } + } + + var settings = RatingSummaryViewSettings() { + didSet { + update() + } + } + + private var isRightToLeft = UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft + + private var type: RatingSummaryViewSettings.ValueType { + switch value { + case 0..<0.2 * maxValue: return .horrible + case 0.2 * maxValue..<0.4 * maxValue: return .bad + case 0.4 * maxValue..<0.6 * maxValue: return .normal + case 0.6 * maxValue..<0.8 * maxValue: return .good + case 0.8 * maxValue...maxValue: return .excellent + default: assert(false) + } + } + + public override func awakeFromNib() { + super.awakeFromNib() + setup() + update() + } + + public convenience init() { + self.init(frame: CGRect()) + } + + public override init(frame: CGRect) { + super.init(frame: frame) + setup() + update() + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() + update() + } + + private func setup() { + layer.backgroundColor = UIColor.clear.cgColor + isOpaque = true + } + + private var viewSize = CGSize() + func updateImpl() { + let sublayer = createLayer() + layer.sublayers = [sublayer] + + viewSize = sublayer.bounds.size + invalidateIntrinsicContentSize() + frame.size = intrinsicContentSize + } + + @objc func doUpdate() { + DispatchQueue.main.async { + self.updateImpl() + } + } + + func update() { + let sel = #selector(doUpdate) + NSObject.cancelPreviousPerformRequests(withTarget: self, selector: sel, object: nil) + perform(sel, with: nil, afterDelay: 1 / 120) + } + + override var intrinsicContentSize: CGSize { + return viewSize + } + + private func createLayer() -> CALayer { + let textLayer = createTextLayer() + return combineLayers(imageLayer: createImageLayer(textLayer.bounds.height), + textLayer: textLayer) + } + + private func combineLayers(imageLayer: CALayer?, textLayer: CALayer) -> CALayer { + var x: CGFloat = 0 + let height = textLayer.bounds.height + settings.topOffset + settings.bottomOffset + let containerLayer = createContainerLayer(height) + if let imageLayer = imageLayer { + x += settings.leadingImageOffset + containerLayer.addSublayer(imageLayer) + imageLayer.position = CGPoint(x: x, y: settings.topOffset) + x += imageLayer.bounds.width + + containerLayer.backgroundColor = settings.colors[type]!.withAlphaComponent(settings.backgroundOpacity).cgColor + containerLayer.cornerRadius = height / 2 + } + + containerLayer.addSublayer(textLayer) + x += settings.margin + textLayer.position = CGPoint(x: x, y: settings.topOffset) + x += textLayer.bounds.width + settings.trailingTextOffset + + containerLayer.bounds.size.width = x + + if isRightToLeft { + let rotation = CATransform3DMakeRotation(CGFloat.pi, 0, 1, 0) + containerLayer.transform = CATransform3DTranslate(rotation, -containerLayer.bounds.size.width, 0, 0) + textLayer.transform = CATransform3DTranslate(rotation, -textLayer.bounds.size.width, 0, 0) + } + return containerLayer + } + + private func createImageLayer(_ size: CGFloat) -> CALayer? { + guard let image = settings.images[type] else { return nil } + let imageLayer = createContainerLayer(size) + imageLayer.contents = image.cgImage + imageLayer.contentsGravity = kCAGravityResizeAspect + + let containerLayer = createContainerLayer(size) + if image.renderingMode == .alwaysTemplate { + containerLayer.mask = imageLayer + containerLayer.backgroundColor = settings.colors[type]!.cgColor + } else { + containerLayer.addSublayer(imageLayer) + } + return containerLayer + } + + private func createTextLayer() -> CALayer { + let font = textFont.withSize(textSize) + let text = String(format: "%.1f", value) + let size = NSString(string: text).size(attributes: [NSFontAttributeName: font]) + + let layer = CATextLayer() + layer.bounds = CGRect(origin: CGPoint(), + size: CGSize(width: ceil(size.width), height: ceil(size.height))) + layer.anchorPoint = CGPoint() + layer.string = text + layer.font = CGFont(font.fontName as CFString) + layer.fontSize = font.pointSize + layer.foregroundColor = settings.colors[type]!.cgColor + layer.contentsScale = UIScreen.main.scale + + return layer + } + + private func createContainerLayer(_ size: CGFloat) -> CALayer { + let layer = CALayer() + layer.bounds = CGRect(origin: CGPoint(), size: CGSize(width: size, height: size)) + layer.anchorPoint = CGPoint() + layer.contentsGravity = kCAGravityResizeAspect + layer.contentsScale = UIScreen.main.scale + layer.masksToBounds = true + layer.isOpaque = true + return layer + } + + override func prepareForInterfaceBuilder() { + super.prepareForInterfaceBuilder() + updateImpl() + } +} diff --git a/iphone/Maps/Classes/Components/RatingSummaryView/RatingSummaryViewSettings.swift b/iphone/Maps/Classes/Components/RatingSummaryView/RatingSummaryViewSettings.swift new file mode 100644 index 0000000000..bfb9b71fe3 --- /dev/null +++ b/iphone/Maps/Classes/Components/RatingSummaryView/RatingSummaryViewSettings.swift @@ -0,0 +1,45 @@ +import UIKit + +struct RatingSummaryViewSettings { + enum ValueType { + case horrible + case bad + case normal + case good + case excellent + } + + enum Default { + static let backgroundOpacity: CGFloat = 0.16 + static let colors: [ValueType: UIColor] = [.horrible: UIColor.red, + .bad: UIColor.orange, + .normal: UIColor.yellow, + .good: UIColor.green, + .excellent: UIColor.blue] + static let images: [ValueType: UIImage] = [:] + static let maxValue: CGFloat = 10 + static let textFont = UIFont.preferredFont(forTextStyle: UIFontTextStyle.footnote) + static let textSize = textFont.pointSize + static let value: CGFloat = 2.2 + static let topOffset: CGFloat = 8 + static let bottomOffset: CGFloat = 8 + static let leadingImageOffset: CGFloat = 12 + static let margin: CGFloat = 8 + static let trailingTextOffset: CGFloat = 8 + } + + init() {} + + var backgroundOpacity = Default.backgroundOpacity + var colors = Default.colors + var images = Default.images + var maxValue = Default.maxValue + var textFont = Default.textFont + var textSize = Default.textSize + var value = Default.value + var topOffset = Default.topOffset + var bottomOffset = Default.bottomOffset + var leadingImageOffset = Default.leadingImageOffset + var margin = Default.margin + var trailingTextOffset = Default.trailingTextOffset +} diff --git a/iphone/Maps/Classes/Components/RatingView/RatingView.swift b/iphone/Maps/Classes/Components/RatingView/RatingView.swift index ff15628943..50779e9bd6 100644 --- a/iphone/Maps/Classes/Components/RatingView/RatingView.swift +++ b/iphone/Maps/Classes/Components/RatingView/RatingView.swift @@ -161,7 +161,7 @@ import UIKit } } - private var texts: [RatingViewSettings.TextSide : String] = [:] { + private var texts: [RatingViewSettings.TextSide: String] = [:] { didSet { update() } } @@ -280,23 +280,23 @@ import UIKit private let isRightToLeft = UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft - override public func awakeFromNib() { + public override func awakeFromNib() { super.awakeFromNib() setup() update() } - convenience public init() { + public convenience init() { self.init(frame: CGRect()) } - override public init(frame: CGRect) { + public override init(frame: CGRect) { super.init(frame: frame) setup() update() } - required public init?(coder aDecoder: NSCoder) { + public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() update() @@ -326,10 +326,10 @@ import UIKit func update() { let sel = #selector(doUpdate) NSObject.cancelPreviousPerformRequests(withTarget: self, selector: sel, object: nil) - perform(sel, with: nil, afterDelay: 1/120) + perform(sel, with: nil, afterDelay: 1 / 120) } - override var intrinsicContentSize : CGSize { + override var intrinsicContentSize: CGSize { return viewSize } @@ -337,7 +337,7 @@ import UIKit return combineLayers(starLayers: createStarLayers(), textLayers: createTextLayers()) } - private func combineLayers(starLayers: [CALayer], textLayers: [RatingViewSettings.TextSide : CALayer]) -> [CALayer] { + private func combineLayers(starLayers: [CALayer], textLayers: [RatingViewSettings.TextSide: CALayer]) -> [CALayer] { var layers = starLayers var starsWidth: CGFloat = 0 layers.forEach { starsWidth = max(starsWidth, $0.position.x + $0.bounds.width) } @@ -422,16 +422,16 @@ import UIKit } } - private func createTextLayers() -> [RatingViewSettings.TextSide : CALayer] { - var layers: [RatingViewSettings.TextSide : CALayer] = [:] + private func createTextLayers() -> [RatingViewSettings.TextSide: CALayer] { + var layers: [RatingViewSettings.TextSide: CALayer] = [:] for (side, text) in texts { let font = settings.textFonts[side]!.withSize(settings.textSizes[side]!) - let size = NSString(string: text).size(attributes: [NSFontAttributeName : font]) + let size = NSString(string: text).size(attributes: [NSFontAttributeName: font]) let layer = CATextLayer() - layer.bounds = CGRect(origin: CGPoint(), size: size) + layer.bounds = CGRect(origin: CGPoint(), + size: CGSize(width: ceil(size.width), height: ceil(size.height))) layer.anchorPoint = CGPoint() - layer.string = text layer.font = CGFont(font.fontName as CFString) layer.fontSize = font.pointSize @@ -510,8 +510,11 @@ import UIKit let path = createStarPath(settings.starPoints, size: size, lineWidth: lineWidth) - let shapeLayer = createShapeLayer(path.cgPath, lineWidth: lineWidth, - fillColor: fillColor, strokeColor: strokeColor, size: size) + let shapeLayer = createShapeLayer(path.cgPath, + lineWidth: lineWidth, + fillColor: fillColor, + strokeColor: strokeColor, + size: size) containerLayer.addSublayer(shapeLayer) } diff --git a/iphone/Maps/Classes/Components/RatingView/RatingViewSettings.swift b/iphone/Maps/Classes/Components/RatingView/RatingViewSettings.swift index 5b4bc5faad..6b10a15f3b 100644 --- a/iphone/Maps/Classes/Components/RatingView/RatingViewSettings.swift +++ b/iphone/Maps/Classes/Components/RatingView/RatingViewSettings.swift @@ -38,28 +38,26 @@ struct RatingViewSettings { static let starType = StarType.boxed static let starPointsBoxSize: CGFloat = 100 - static let starPoints: [StarType : [CGPoint]] = [ - StarType.regular : [CGPoint(x: 49.5, y: 0.0), - CGPoint(x: 60.5, y: 35.0), - CGPoint(x: 99.0, y: 35.0), - CGPoint(x: 67.5, y: 58.0), - CGPoint(x: 78.5, y: 92.0), - CGPoint(x: 49.5, y: 71.0), - CGPoint(x: 20.5, y: 92.0), - CGPoint(x: 31.5, y: 58.0), - CGPoint(x: 0.0, y: 35.0), - CGPoint(x: 38.5, y: 35.0)], - StarType.boxed : [CGPoint(x: 50.5, y: 22.2), - CGPoint(x: 57.6, y: 45.6), - CGPoint(x: 79.9, y: 45.6), - CGPoint(x: 61.7, y: 58.1), - CGPoint(x: 68.6, y: 78.8), - CGPoint(x: 50.5, y: 66.0), - CGPoint(x: 32.4, y: 78.8), - CGPoint(x: 39.3, y: 58.1), - CGPoint(x: 21.2, y: 45.6), - CGPoint(x: 43.4, y: 45.6)] - ] + static let starPoints: [StarType: [CGPoint]] = [StarType.regular: [CGPoint(x: 49.5, y: 0.0), + CGPoint(x: 60.5, y: 35.0), + CGPoint(x: 99.0, y: 35.0), + CGPoint(x: 67.5, y: 58.0), + CGPoint(x: 78.5, y: 92.0), + CGPoint(x: 49.5, y: 71.0), + CGPoint(x: 20.5, y: 92.0), + CGPoint(x: 31.5, y: 58.0), + CGPoint(x: 0.0, y: 35.0), + CGPoint(x: 38.5, y: 35.0)], + StarType.boxed: [CGPoint(x: 50.5, y: 22.2), + CGPoint(x: 57.6, y: 45.6), + CGPoint(x: 79.9, y: 45.6), + CGPoint(x: 61.7, y: 58.1), + CGPoint(x: 68.6, y: 78.8), + CGPoint(x: 50.5, y: 66.0), + CGPoint(x: 32.4, y: 78.8), + CGPoint(x: 39.3, y: 58.1), + CGPoint(x: 21.2, y: 45.6), + CGPoint(x: 43.4, y: 45.6)]] } init() {} @@ -67,29 +65,29 @@ struct RatingViewSettings { var borderWidth = Default.borderWidth var emptyBorderColor = Default.emptyBorderColor var emptyColor = Default.emptyColor - var emptyImage: UIImage? = nil + var emptyImage: UIImage? var fillMode = Default.fillMode var filledBorderColor = Default.filledBorderColor var filledColor = Default.filledColor - var filledImage: UIImage? = nil + var filledImage: UIImage? var minTouchRating = Default.minTouchRating - var textColors: [TextSide : UIColor] = [.left : Default.textColor, - .right : Default.textColor, - .top : Default.textColor, - .bottom : Default.textColor] - var textFonts: [TextSide : UIFont] = [.left : Default.textFont, - .right : Default.textFont, - .top : Default.textFont, - .bottom : Default.textFont] - var textSizes: [TextSide : CGFloat] = [.left : Default.textSize, - .right : Default.textSize, - .top : Default.textSize, - .bottom : Default.textSize] - var textMargins: [TextSide : CGFloat] = [.left : Default.textMargin, - .right : Default.textMargin, - .top : Default.textMargin, - .bottom : Default.textMargin] + var textColors: [TextSide: UIColor] = [.left: Default.textColor, + .right: Default.textColor, + .top: Default.textColor, + .bottom: Default.textColor] + var textFonts: [TextSide: UIFont] = [.left: Default.textFont, + .right: Default.textFont, + .top: Default.textFont, + .bottom: Default.textFont] + var textSizes: [TextSide: CGFloat] = [.left: Default.textSize, + .right: Default.textSize, + .top: Default.textSize, + .bottom: Default.textSize] + var textMargins: [TextSide: CGFloat] = [.left: Default.textMargin, + .right: Default.textMargin, + .top: Default.textMargin, + .bottom: Default.textMargin] var starMargin = Default.starMargin var starPoints = Default.starPoints[Default.starType]! diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index 17d64d0a95..0158dbe0e8 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -230,6 +230,12 @@ 3444DFDE1F18A5AF00E73099 /* SideButtonsArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3444DFDC1F18A5AF00E73099 /* SideButtonsArea.swift */; }; 3444DFDF1F18A5AF00E73099 /* SideButtonsArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3444DFDC1F18A5AF00E73099 /* SideButtonsArea.swift */; }; 3446C6771DDCA9A200146687 /* libtraffic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3446C6761DDCA9A200146687 /* libtraffic.a */; }; + 344BEAF21F66BDC30045DC45 /* RatingSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344BEAF01F66BDC30045DC45 /* RatingSummaryView.swift */; }; + 344BEAF31F66BDC30045DC45 /* RatingSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344BEAF01F66BDC30045DC45 /* RatingSummaryView.swift */; }; + 344BEAF41F66BDC30045DC45 /* RatingSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344BEAF01F66BDC30045DC45 /* RatingSummaryView.swift */; }; + 344BEAF51F66BDC30045DC45 /* RatingSummaryViewSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344BEAF11F66BDC30045DC45 /* RatingSummaryViewSettings.swift */; }; + 344BEAF61F66BDC30045DC45 /* RatingSummaryViewSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344BEAF11F66BDC30045DC45 /* RatingSummaryViewSettings.swift */; }; + 344BEAF71F66BDC30045DC45 /* RatingSummaryViewSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344BEAF11F66BDC30045DC45 /* RatingSummaryViewSettings.swift */; }; 344D63171E795A2D006F17CB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 344D63161E795A2D006F17CB /* SystemConfiguration.framework */; }; 344D63181E795A3C006F17CB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 344D63161E795A2D006F17CB /* SystemConfiguration.framework */; }; 344D63191E795A3C006F17CB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 344D63161E795A2D006F17CB /* SystemConfiguration.framework */; }; @@ -1872,6 +1878,8 @@ 3444DFD01F17620C00E73099 /* MWMMapWidgetsHelper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMMapWidgetsHelper.mm; sourceTree = ""; }; 3444DFDC1F18A5AF00E73099 /* SideButtonsArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideButtonsArea.swift; sourceTree = ""; }; 3446C6761DDCA9A200146687 /* libtraffic.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtraffic.a; path = "../../../omim-build/xcode/Debug/libtraffic.a"; sourceTree = ""; }; + 344BEAF01F66BDC30045DC45 /* RatingSummaryView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RatingSummaryView.swift; sourceTree = ""; }; + 344BEAF11F66BDC30045DC45 /* RatingSummaryViewSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RatingSummaryViewSettings.swift; sourceTree = ""; }; 344D63161E795A2D006F17CB /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 345050211E028B8000A8DC59 /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; 3451F4EC1F026DAF00A981F2 /* PlacePageTaxiCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlacePageTaxiCell.swift; sourceTree = ""; }; @@ -3174,6 +3182,15 @@ path = Ads; sourceTree = ""; }; + 344BEAEF1F66BDC30045DC45 /* RatingSummaryView */ = { + isa = PBXGroup; + children = ( + 344BEAF01F66BDC30045DC45 /* RatingSummaryView.swift */, + 344BEAF11F66BDC30045DC45 /* RatingSummaryViewSettings.swift */, + ); + path = RatingSummaryView; + sourceTree = ""; + }; 3454D7981E07F045004AF2AD /* Categories */ = { isa = PBXGroup; children = ( @@ -3339,30 +3356,31 @@ 346EDAD81B9F0E15004F8DB5 /* Components */ = { isa = PBXGroup; children = ( - 348A8DF01F66775A00D83026 /* RatingView */, F653CE131C71F5DC00A453F1 /* AddPlace NavigationBar */, + 3470402E1EA6470700038379 /* BorderedButton.swift */, + 340708761F2B5D6C00029ECC /* DimBackground.swift */, F652B2E81C6DE8CF00D20C8C /* DropDown */, + F6FEA82B1C58E89B007223CC /* MWMButton.h */, + F6FEA82C1C58E89B007223CC /* MWMButton.mm */, + 343E75951E5B1EE20041226A /* MWMCollectionViewController.h */, + 343E75961E5B1EE20041226A /* MWMCollectionViewController.mm */, + 34C9BD061C6DB6F3000DC38D /* MWMController.h */, + 34B924401DC8A29C0008D971 /* MWMMailViewController.h */, + 34B924411DC8A29C0008D971 /* MWMMailViewController.mm */, 346EDAD91B9F0E35004F8DB5 /* MWMMultilineLabel.h */, 346EDADA1B9F0E35004F8DB5 /* MWMMultilineLabel.mm */, + 34C9BD071C6DBCDA000DC38D /* MWMNavigationController.h */, + 34C9BD081C6DBCDA000DC38D /* MWMNavigationController.mm */, F6791B111C43DEA7007A8A6E /* MWMStartButton.h */, F6791B121C43DEA7007A8A6E /* MWMStartButton.mm */, 34AB39BF1D2BD8310021857D /* MWMStopButton.h */, 34AB39C01D2BD8310021857D /* MWMStopButton.mm */, - F6FEA82B1C58E89B007223CC /* MWMButton.h */, - F6FEA82C1C58E89B007223CC /* MWMButton.mm */, - 34C9BD061C6DB6F3000DC38D /* MWMController.h */, 34C9BCFE1C6DB693000DC38D /* MWMTableViewController.h */, 34C9BCFF1C6DB693000DC38D /* MWMTableViewController.mm */, 34C9BD001C6DB693000DC38D /* MWMViewController.h */, 34C9BD011C6DB693000DC38D /* MWMViewController.mm */, - 34C9BD071C6DBCDA000DC38D /* MWMNavigationController.h */, - 34C9BD081C6DBCDA000DC38D /* MWMNavigationController.mm */, - 34B924401DC8A29C0008D971 /* MWMMailViewController.h */, - 34B924411DC8A29C0008D971 /* MWMMailViewController.mm */, - 343E75951E5B1EE20041226A /* MWMCollectionViewController.h */, - 343E75961E5B1EE20041226A /* MWMCollectionViewController.mm */, - 3470402E1EA6470700038379 /* BorderedButton.swift */, - 340708761F2B5D6C00029ECC /* DimBackground.swift */, + 344BEAEF1F66BDC30045DC45 /* RatingSummaryView */, + 348A8DF01F66775A00D83026 /* RatingView */, ); path = Components; sourceTree = ""; @@ -5488,6 +5506,7 @@ files = ( 34845DB61E166084003D55B9 /* Common.swift in Sources */, 349993FD1F388F970064CFBE /* RouteManageriPhonePresentationController.swift in Sources */, + 344BEAF21F66BDC30045DC45 /* RatingSummaryView.swift in Sources */, 1D60589B0D05DD56006BFB54 /* main.mm in Sources */, 34D3B04E1E38A20C004100F9 /* Bundle+Init.swift in Sources */, 340837161B72451A00B5C185 /* MWMShareActivityItem.mm in Sources */, @@ -5755,6 +5774,7 @@ 3404164B1E7BF42E00E2B6D6 /* UIView+Coordinates.swift in Sources */, 349D1ADA1E2E325C004A2006 /* MWMBottomMenuView.mm in Sources */, F6E2FD911E097BA00083EBEC /* MWMBookmarkColorViewController.mm in Sources */, + 344BEAF51F66BDC30045DC45 /* RatingSummaryViewSettings.swift in Sources */, F643247A1EF82AD9009296F9 /* UGCSelectImpressionCell.swift in Sources */, F63AF5051EA6162400A1DB98 /* FilterTypeCell.swift in Sources */, F6E2FDA31E097BA00083EBEC /* MWMCuisineEditorViewController.mm in Sources */, @@ -5828,6 +5848,7 @@ files = ( 34845DB71E166084003D55B9 /* Common.swift in Sources */, 349993FE1F388F970064CFBE /* RouteManageriPhonePresentationController.swift in Sources */, + 344BEAF31F66BDC30045DC45 /* RatingSummaryView.swift in Sources */, 6741A9A31BF340DE002C974C /* main.mm in Sources */, 34D3B04F1E38A20C004100F9 /* Bundle+Init.swift in Sources */, F6E2FF541E097BA00083EBEC /* MWMHelpController.mm in Sources */, @@ -6095,6 +6116,7 @@ 6741AA141BF340DE002C974C /* MWMMultilineLabel.mm in Sources */, 349D1ADB1E2E325C004A2006 /* MWMBottomMenuView.mm in Sources */, 3407085A1F28F1F400029ECC /* MWMTaxiPreviewDataSource.mm in Sources */, + 344BEAF61F66BDC30045DC45 /* RatingSummaryViewSettings.swift in Sources */, F6E2FD921E097BA00083EBEC /* MWMBookmarkColorViewController.mm in Sources */, F643247B1EF82AD9009296F9 /* UGCSelectImpressionCell.swift in Sources */, F63AF5061EA6162400A1DB98 /* FilterTypeCell.swift in Sources */, @@ -6168,6 +6190,7 @@ files = ( 34845DB81E166084003D55B9 /* Common.swift in Sources */, 349993FF1F388F970064CFBE /* RouteManageriPhonePresentationController.swift in Sources */, + 344BEAF41F66BDC30045DC45 /* RatingSummaryView.swift in Sources */, 849CF6821DE842290024A8A5 /* main.mm in Sources */, 34D3B0501E38A20C004100F9 /* Bundle+Init.swift in Sources */, 3454D7D51E07F045004AF2AD /* UIImageView+Coloring.mm in Sources */, @@ -6435,6 +6458,7 @@ 3404164D1E7BF42E00E2B6D6 /* UIView+Coordinates.swift in Sources */, F6E2FD931E097BA00083EBEC /* MWMBookmarkColorViewController.mm in Sources */, 3407085B1F28F1F400029ECC /* MWMTaxiPreviewDataSource.mm in Sources */, + 344BEAF71F66BDC30045DC45 /* RatingSummaryViewSettings.swift in Sources */, 849CF7331DE842290024A8A5 /* MWMInputValidatorFactory.mm in Sources */, F6E2FDA51E097BA00083EBEC /* MWMCuisineEditorViewController.mm in Sources */, F643247C1EF82AD9009296F9 /* UGCSelectImpressionCell.swift in Sources */,