diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 9215b753..779cd132 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -49,7 +49,7 @@ 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 /* ColorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B35239813EE0067DD0F /* ColorModel.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 */; }; @@ -282,7 +282,7 @@ 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 /* ColorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorModel.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 = ""; }; @@ -532,7 +532,7 @@ 0AA33B322398134B0067DD0F /* Primitive Models */ = { isa = PBXGroup; children = ( - 0AA33B35239813EE0067DD0F /* ColorModel.swift */, + 0AA33B35239813EE0067DD0F /* Color.swift */, ); path = "Primitive Models"; sourceTree = ""; @@ -1288,7 +1288,7 @@ 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */, D22479962316AF6E003FCCF9 /* HeadlineBodyTextButton.swift in Sources */, - 0AA33B36239813EE0067DD0F /* ColorModel.swift in Sources */, + 0AA33B36239813EE0067DD0F /* Color.swift in Sources */, D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */, 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */, D29DF18121E69E50003B2FB9 /* MFView.m in Sources */, diff --git a/MVMCoreUI/Categories/UIColor+Extension.swift b/MVMCoreUI/Categories/UIColor+Extension.swift index 56986044..fab1ae6f 100644 --- a/MVMCoreUI/Categories/UIColor+Extension.swift +++ b/MVMCoreUI/Categories/UIColor+Extension.swift @@ -9,8 +9,27 @@ import UIKit +public typealias ColorHexTuple = (uiColor: UIColor, hex: String) extension UIColor { + + /// Dictionary to access brand approved colors by name. + public static let names: [String: ColorHexTuple] = ["black": (.mvmBlack, "#000000"), + "white": (.mvmWhite, "#FFFFFF"), + "red": (.mvmRed, "#D52B1E"), + "orange": (.mvmOrange, "#CC4D0F"), + "green": (.mvmGreen, "#008631"), + "blue": (.mvmBlue, "#007AB8"), + "blueGradient": (.mvmBlueGradient, "#007AB8"), + "yellow": (.mvmYellow, "#FFBC3D"), + "coolGray1": (.mvmCoolGray1, "#F6F6F6"), + "coolGray3": (.mvmCoolGray3, "#D8DADA"), + "coolGray6": (.mvmCoolGray6, "#747676"), + "vzupGold": (.vzupGold, "#B89B56"), + "vzupYellow1": (.vzupYellow1, "#F9D542"), + "vzupYellow2": (.vzupYellow2, "#F4CA53"), + "vzupYellow3": (.vzupYellow3, "#CC9B2D")] + //-------------------------------------------------- // MARK: - Brand //-------------------------------------------------- @@ -22,47 +41,47 @@ extension UIColor { public static let mvmWhite = UIColor.white /// HEX: #D52B1E - public static let mvmRed = UIColor.getColor(red: 213, green: 43, blue: 30) + public static let mvmRed = UIColor.color8Bits(red: 213, green: 43, blue: 30) /// HEX: #CC4D0F - public static let mvmOrange = UIColor.getColor(red: 204, green: 77, blue: 15) + public static let mvmOrange = UIColor.color8Bits(red: 204, green: 77, blue: 15) /// HEX: #008631 - public static let mvmGreen = UIColor.getColor(red: 0, green: 134, blue: 49) + public static let mvmGreen = UIColor.color8Bits(red: 0, green: 134, blue: 49) /// HEX: #007AB8 - public static let mvmBlue = UIColor.getColor(red: 0, green: 122, blue: 184) + public static let mvmBlue = UIColor.color8Bits(red: 0, green: 122, blue: 184) /// HEX: #007AB8 - public static let mvmBlueGradient = UIColor.getColor(red: 0, green: 122, blue: 184) + public static let mvmBlueGradient = UIColor.color8Bits(red: 0, green: 122, blue: 184) /// HEX: #FFBC3D - public static let mvmYellow = UIColor.getColor(red: 255, green: 188, blue: 61) + public static let mvmYellow = UIColor.color8Bits(red: 255, green: 188, blue: 61) /// HEX: #F6F6F6 public static let mvmCoolGray1 = UIColor.grayscale(rgb: 246) /// HEX: #D8DADA - public static let mvmCoolGray3 = UIColor.getColor(red: 216, green: 218, blue: 218) + public static let mvmCoolGray3 = UIColor.color8Bits(red: 216, green: 218, blue: 218) /// HEX: #747676 - public static let mvmCoolGray6 = UIColor.getColor(red: 116, green: 118, blue: 118) + public static let mvmCoolGray6 = UIColor.color8Bits(red: 116, green: 118, blue: 118) //-------------------------------------------------- // MARK: - VZ UP Brand //-------------------------------------------------- /// HEX: #B89B56 - public static let vzupGold = UIColor.getColor(red: 184, green: 155, blue: 68) + public static let vzupGold = UIColor.color8Bits(red: 184, green: 155, blue: 68) /// HEX: #F9D542 - public static let vzupYellow1 = UIColor.getColor(red: 249, green: 213, blue: 66) + public static let vzupYellow1 = UIColor.color8Bits(red: 249, green: 213, blue: 66) /// HEX: #F4CA53 - public static let vzupYellow2 = UIColor.getColor(red: 244, green: 202, blue: 83) + public static let vzupYellow2 = UIColor.color8Bits(red: 244, green: 202, blue: 83) /// HEX: #CC9B2D - public static let vzupYellow3 = UIColor.getColor(red: 204, green: 155, blue: 45) + public static let vzupYellow3 = UIColor.color8Bits(red: 204, green: 155, blue: 45) //-------------------------------------------------- // MARK: - Functions @@ -75,14 +94,14 @@ extension UIColor { return UIColor(red: grayscale, green: grayscale, blue: grayscale, alpha: alpha) } - /// Convenience to get a UIColor via Int. - public class func getColor(red: Int, green: Int, blue: Int, alpha: CGFloat = 1.0) -> UIColor { + /// Convenience to get a UIColor. + public class func color8Bits(red: Int, green: Int, blue: Int, alpha: CGFloat = 1.0) -> UIColor { return UIColor(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: alpha) } - /// Convenience to get a UIColor via CGFloat. - public class func getColor(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat = 1.0) -> UIColor { + /// Convenience to get a UIColor. + public class func color8Bits(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat = 1.0) -> UIColor { return UIColor(red: red / 255.0, green: green / 255.0, blue: blue / 255.0, alpha: alpha) } @@ -90,11 +109,11 @@ extension UIColor { /// Gets UIColor via an 8 digit hex string. public class func getColorBy(hex: String) -> UIColor { - var hexint: UInt32 = 0 + var hexint: UInt64 = 0 let scanner = Scanner(string: hex) scanner.charactersToBeSkipped = CharacterSet(charactersIn: "#") - scanner.scanHexInt32(&hexint) + scanner.scanHexInt64(&hexint) return UIColor(red: (CGFloat((hexint & 0xFF0000) >> 16)) / 255, green: (CGFloat((hexint & 0xFF00) >> 8)) / 255, @@ -105,11 +124,11 @@ extension UIColor { /// Gets UIColor via an 8 digit hex string. The last two being the alpha channel. public class func getColorWithTransparencyBy(hex: String) -> UIColor { - var hexint: UInt32 = 0 + var hexint: UInt64 = 0 let scanner = Scanner(string: hex) scanner.charactersToBeSkipped = CharacterSet(charactersIn: "#") - scanner.scanHexInt32(&hexint) + scanner.scanHexInt64(&hexint) return UIColor(red: (CGFloat((hexint & 0xFF000000) >> 24)) / 255, green: (CGFloat((hexint & 0xFF0000) >> 16)) / 255, @@ -177,4 +196,15 @@ extension UIColor { return nil } + + public class func getColorAndHexFromName(_ name: String) -> ColorHexTuple? { + + for row in names { + if name == row.key { + return row.value + } + } + + return nil + } } diff --git a/MVMCoreUI/Models/Primitive Models/ColorModel.swift b/MVMCoreUI/Models/Primitive Models/Color.swift similarity index 63% rename from MVMCoreUI/Models/Primitive Models/ColorModel.swift rename to MVMCoreUI/Models/Primitive Models/Color.swift index 68fb16de..cafe5915 100644 --- a/MVMCoreUI/Models/Primitive Models/ColorModel.swift +++ b/MVMCoreUI/Models/Primitive Models/Color.swift @@ -1,5 +1,5 @@ // -// ColorModel.swift +// Color.swift // MVMCoreUI // // Created by Kevin Christiano on 11/26/19. @@ -8,40 +8,49 @@ import UIKit -/** - Allows Hex values to be modeled into a UIColor object with its surrounding metadata. - */ -open class ColorModel: Codable { + +public final class Color: Codable { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - static var identifier: String = "color" - public let uiColor: UIColor - public var hex: String = "" + public private(set) var hex: String = "" + public private(set) var name: String = "" - public var red: CGFloat = 0 - public var green: CGFloat = 0 - public var blue: CGFloat = 0 - public var alpha: CGFloat = 1 + // Color metadata + public private(set) var red: CGFloat = 0 + public private(set) var green: CGFloat = 0 + public private(set) var blue: CGFloat = 0 + public private(set) var alpha: CGFloat = 1 public var hexWithHash: String { return "#" + hex } //-------------------------------------------------- - // MARK: - Class Initializer + // MARK: - Error + //-------------------------------------------------- + + enum ColorError: Error { + case badName(reason: String) + } + + //-------------------------------------------------- + // MARK: - Class Initializers //-------------------------------------------------- init(uiColor: UIColor) { self.uiColor = uiColor - hex = UIColor.hexString(for: uiColor) ?? "" - - if !hex.isEmpty { - determineRGBA() - } + determineRGBA() + } + + init?(name: String) { + guard let colorTuple = UIColor.getColorAndHexFromName(name) else { return nil } + self.uiColor = colorTuple.uiColor + self.hex = colorTuple.hex + determineRGBA() } //-------------------------------------------------- @@ -50,7 +59,15 @@ open class ColorModel: Codable { required public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() - hex = try container.decode(String.self).replacingOccurrences(of: "#", with: "") + let colorString = try container.decode(String.self) + + if colorString.hasPrefix("#") { + hex = colorString.replacingOccurrences(of: "#", with: "") + } else { + guard let hex = UIColor.getColorAndHexFromName(colorString)?.hex else { throw ColorError.badName(reason: "Check the spelling of your color.") } + self.hex = hex.replacingOccurrences(of: "#", with: "") + name = colorString + } if hex.count == 8 { uiColor = UIColor.getColorWithTransparencyBy(hex: hex) @@ -77,6 +94,8 @@ open class ColorModel: Codable { private func determineRGBA() { + guard !hex.isEmpty else { return } + let redStart = hex.startIndex let redEnd = hex.index(redStart, offsetBy: 2) red = convertHexToFloat(start: redStart, end: redEnd)