// // TileContainer.swift // VDS // // Created by Matt Bruce on 12/16/22. // import Foundation import VDSColorTokens import UIKit open class TileContainer: Control { public enum ContainerBackgroundColor: String, CaseIterable { case white case black case gray case transparent } public enum ContainerPadding: String, CaseIterable { case twelve = "12" case sixteen = "16" case twentyFour = "24" case thirtyTwo = "32" case fourtyEight = "48" } public enum ContainerScalingType: String, CaseIterable { case ratio1x1 = "1:1" case ratio3x4 = "3:4" case ratio4x3 = "4:3" case ratio2x3 = "2:3" case ratio3x2 = "3:2" case ratio9x16 = "9:16" case ratio16x9 = "16:9" case ratio1x2 = "1:2" case ratio2x1 = "2:1" } //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- public var backgroundImage: UIImage? { didSet{ didChange() } } public var containerView = View() public var highlightView = View() public var containerBackgroundColor: ContainerBackgroundColor = .white { didSet{ didChange() } } public var containerPadding: ContainerPadding = .sixteen { didSet{ didChange() } } public var aspectRatio: ContainerScalingType = .ratio1x1 { didSet{ didChange() } } public var imageFallbackColor: Surface = .light { didSet{ didChange() } } private var _width: CGFloat = 100 public var width: CGFloat { get { return _width } set { if newValue > 100 { _width = newValue didChange() } } } public var height: CGFloat? { didSet{ didChange() } } public var showBorder: Bool = false { didSet{ didChange() } } public var showDropShadows: Bool = false { didSet{ didChange() } } //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- private var backgroundImageView = UIImageView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.contentMode = .scaleAspectFill $0.clipsToBounds = true } private var padding: CGFloat { switch containerPadding { case .twelve: return 12.0 case .sixteen: return 16.0 case .twentyFour: return 24.0 case .thirtyTwo: return 32.0 case .fourtyEight: return 48.0 } } //-------------------------------------------------- // MARK: - Constraints //-------------------------------------------------- private lazy var widthConstraint: NSLayoutConstraint = { let constraint = widthAnchor.constraint(equalToConstant: width) constraint.isActive = true return constraint }() private lazy var heightConstraint: NSLayoutConstraint = { let constraint = heightAnchor.constraint(equalToConstant: 100) constraint.isActive = true return constraint }() //functions //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- open override func setup() { super.setup() addSubview(backgroundImageView) addSubview(containerView) addSubview(highlightView) backgroundImageView.pinToSuperView() backgroundImageView.isUserInteractionEnabled = false backgroundImageView.isHidden = true containerView.pinToSuperView() containerView.isUserInteractionEnabled = false containerView.backgroundColor = .clear highlightView.pinToSuperView() highlightView.isUserInteractionEnabled = false highlightView.isHidden = true highlightView.backgroundColor = .clear //corner radius layer.cornerRadius = cornerRadius backgroundImageView.layer.cornerRadius = 8 } public override func reset() { super.reset() } //-------------------------------------------------- // MARK: - Configuration //-------------------------------------------------- private let cornerRadius = 8.0 private var backgroundColorConfig = BackgroundColorConfiguration() private var borderColorConfig = SurfaceColorConfiguration().with { $0.lightColor = VDSColor.elementsLowContrastOnLight $0.darkColor = VDSColor.elementsLowContrastOnDark } private var imageFallbackColorConfig = SurfaceColorConfiguration().with { $0.lightColor = VDSColor.backgroundPrimaryLight $0.darkColor = VDSColor.backgroundPrimaryDark } private var hightLightViewColorConfig = SurfaceColorConfiguration().with { $0.lightColor = VDSColor.paletteWhite.withAlphaComponent(0.3) $0.darkColor = VDSColor.paletteBlack.withAlphaComponent(0.3) } //-------------------------------------------------- // MARK: - State //-------------------------------------------------- var ratioSize: CGSize { var height: CGFloat = width switch aspectRatio { case .ratio1x1: break; case .ratio3x4: height = (4 / 3) * width case .ratio4x3: height = (3 / 4) * width case .ratio2x3: height = (3 / 2) * width case .ratio3x2: height = (2 / 3) * width case .ratio9x16: height = (16 / 9) * width case .ratio16x9: height = (9 / 16) * width case .ratio1x2: height = (2 / 1) * width case .ratio2x1: height = (1 / 2) * width } return CGSize(width: width, height: height) } open override func updateView() { super.updateView() highlightView.backgroundColor = hightLightViewColorConfig.getColor(self) highlightView.isHidden = !isHighlighted if let backgroundImage { backgroundImageView.image = backgroundImage backgroundImageView.isHidden = false backgroundColor = imageFallbackColorConfig.getColor(self) } else { backgroundImageView.isHidden = true backgroundColor = backgroundColorConfig.getColor(self) } layer.borderColor = borderColorConfig.getColor(self).cgColor layer.borderWidth = showBorder ? 1 : 0 containerView.layoutMargins = UIEdgeInsets(top: padding, left: padding, bottom: padding, right: padding) if let height { widthConstraint.constant = width heightConstraint.constant = height } else { let size = ratioSize widthConstraint.constant = size.width heightConstraint.constant = size.height } } class BackgroundColorConfiguration: ObjectColorable { typealias ObjectType = TileContainer required init() { } func getColor(_ object: TileContainer) -> UIColor { switch object.containerBackgroundColor { case .white: return VDSColor.backgroundPrimaryLight case .black: return VDSColor.backgroundPrimaryDark case .gray: return VDSColor.backgroundSecondaryLight case .transparent: return UIColor.clear } } } }