vds_ios/VDS/Classes/ColorConfiguration.swift
Matt Bruce 6b97472103 bug for configuration
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2023-06-05 11:56:56 -05:00

210 lines
8.2 KiB
Swift

//
// ModelColorConfiguration.swift
// VDS
//
// Created by Matt Bruce on 8/4/22.
//
import Foundation
import UIKit
public typealias ObjectColorable = Colorable & Initable & ObjectWithable
/// Meant to be used in a Object that implements the following interfaces for 2 possible color combinations
/// - Surfaceable (var surface: Surface)
///
/// let model = TestModel()
/// model.surface = .light
///
/// let config = SurfaceColorConfiguration()
/// config.lightColor = .black
/// config.darkColor = .white
///
/// let textColor = config.getColor(model) //returns .black
///
/// You can pass in a Surfaceable object and it will give you the color responding.
open class SurfaceColorConfiguration: ObjectColorable {
public typealias ObjectType = Surfaceable
public var lightColor: UIColor = .clear
public var darkColor: UIColor = .clear
required public init(){}
/// Inititialization
/// - Parameters:
/// - lightColor: Color used for a light surface
/// - darkColor: Color used for a dark surface
public init(_ lightColor: UIColor, _ darkColor: UIColor) {
self.lightColor = lightColor
self.darkColor = darkColor
}
/// Will get the UIColor for the surface passed in
/// - Parameter surface: surface you currently have
/// - Returns: color corresponding to the surface you passed
public func getColor(_ surface: Surface) -> UIColor {
return surface == .light ? lightColor : darkColor
}
/// Colorable Generic method that will only take in any object that has a Surfacable implementation
/// - Parameter object: any Surfacable object type
/// - Returns: UIColor for the object type you passed in
public func getColor(_ object: any ObjectType) -> UIColor {
return getColor(object.surface)
}
}
/// Struct to Hold onto KeyType and SurfaceConfiguration
public struct KeyColorConfiguration<KeyType: Equatable> {
var key: KeyType
var surfaceConfig: SurfaceColorConfiguration
}
// Protocol to Hold onto the relationship of KeyType and SurfaceConfiguration
public protocol KeyColorConfigurable: ObjectColorable {
associatedtype KeyType: Equatable
var keyColors: [KeyColorConfiguration<KeyType>] { get set }
}
extension KeyColorConfigurable {
/// Generic Method to set a KeyColorConfiguration with the parameters given
/// - Parameters:
/// - lightColor: Color used for a light
/// - darkColor: Color used for a dark
/// - key: <#key description#>
public func setSurfaceColors(_ lightColor: UIColor, _ darkColor: UIColor, forKey key: KeyType) {
keyColors.append(.init(key: key, surfaceConfig: .init(lightColor, darkColor)))
}
/// Removes all keyColors
public func reset() {
keyColors.removeAll()
}
}
extension KeyColorConfigurable where ObjectType: Surfaceable {
/// Default Implementation for when the ObjectType is a Surfacable
/// - Parameters:
/// - object: Surfaceable ObjectType
/// - key: KeyPath to the property of the ObjectType
/// - Returns: UIColor corresponding the the key and surface
public func getColor(for object: ObjectType, with key: KeyType) -> UIColor {
if let keyColor = keyColors.first(where: {$0.key == key }) {
return keyColor.surfaceConfig.getColor(object)
} else {
return .clear //default
}
}
}
/// ColorConfiguration for UIControls and will implement KeyColorConfigurale. This will then use the
/// register a SurfaceColorConfiguration for each state.
public class ControlColorConfiguration: KeyColorConfigurable {
public typealias KeyType = UIControl.State
public typealias ObjectType = Surfaceable & UIControl
public var keyColors: [KeyColorConfiguration<KeyType>] = []
public required init() { }
/// Helper method to set the SurfaceColorConfiguration for a state
/// - Parameters:
/// - lightColor: Color used for a light
/// - darkColor: Color used for a dark
/// - state: UIControlState you are keying off of.
public func setSurfaceColors(_ lightColor: UIColor, _ darkColor: UIColor, forState state: KeyType) {
setSurfaceColors(lightColor, darkColor, forKey: state)
}
/// Colorable implementation for getColor that where the object passed in will be of a UIControl as well as implementing Surfaceable.
/// - Parameter object: Object that is of UIControl and implements Surfacable
/// - Returns: UIColor corresponding to the UIControl.state and surface property of this object.
public func getColor(_ object: any ObjectType) -> UIColor {
let state = object.state
let surface = object.surface
if let keyColor = keyColors.first(where: {$0.key == state }) {
return keyColor.surfaceConfig.getColor(surface)
} else if let keyColor = keyColors.first(where: {$0.key.isSubset(of: state) }) {
return keyColor.surfaceConfig.getColor(surface)
} else {
return .clear
}
}
}
///Meant to be used with any object that implements Surfaceable and Disabling. More than likely this is any View.
public class ViewColorConfiguration: KeyColorConfigurable {
public typealias KeyType = Bool
public typealias ObjectType = Surfaceable & Disabling
public var keyColors: [KeyColorConfiguration<KeyType>] = []
public required init() { }
/// Helper method to set the SurfaceColorConfiguration based on whether the object is disabled or not.
/// - Parameters:
/// - lightColor: Color used for a light
/// - darkColor: Color used for a dark
/// - disabled: True/False for disabled property
public func setSurfaceColors(_ lightColor: UIColor, _ darkColor: UIColor, forDisabled disabled: KeyType) {
setSurfaceColors(lightColor, darkColor, forKey: disabled)
}
/// Colorable implementation for getColor that where the object passed in will any object that implementing Surfaceable and Disabling.
/// - Parameter object: Object that implements Surfaceable and Disabling
/// - Returns: UIColor correspoding to either true/false for the disabled state and surface
public func getColor(_ object: ObjectType) -> UIColor {
if let keyColor = keyColors.first(where: {$0.key == object.disabled }) {
return keyColor.surfaceConfig.getColor(object)
} else {
return .clear //default
}
}
}
/// Generic Class that allows reflection for a object's specific property (equatable) to be defined as the lookup for a SurfaceConfiguration
public class KeyedColorConfiguration<ObjectType: Surfaceable, KeyType: Equatable> : KeyColorConfigurable {
//Type of Class that at least implements Surfaceable
public typealias ObjectType = ObjectType
//where the value exist for the object
public var keyPath: KeyPath<ObjectType, KeyType>?
/// Array of structs where the KeyValue is registered against a SurfaceColorConfiguration
public var keyColors: [KeyColorConfiguration<KeyType>] = []
public required init() {}
//this must be used
public required convenience init(keyPath: KeyPath<ObjectType, KeyType>) {
self.init()
self.keyPath = keyPath
}
/// Finds the KeyColorConfiguration for the Object passed in.
/// - Parameter object: Object should be of Surfaceable
/// - Returns: KeyType for the Object passed in
public func getKeyValue(_ object: ObjectType) -> KeyType? {
guard let keyPath else { fatalError("keyPath must not be empty, make sure you initialize this class using init(keyPath: \\Object.property) method") }
return object[keyPath: keyPath]
}
/// Colorable implementation for getColor that where the object passed in will any object that implementing Surfaceable for the KeyPath registered.
/// - Parameter object: Object matching the type registered
/// - Returns: UIColor for the Object pertaining to the KeyPath it was registered
public func getColor(_ object: ObjectType) -> UIColor {
if let key = getKeyValue(object), let keyColor = keyColors.first(where: {$0.key == key }) {
return keyColor.surfaceConfig.getColor(object)
} else {
return .clear //default
}
}
}