vds_ios/VDS/Components/Checkbox/Checkbox.swift
Matt Bruce c9cc612698 updated for withable on lazy properties
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2022-08-22 15:35:45 -05:00

141 lines
6.0 KiB
Swift

//
// Checkbox.swift
// VDS
//
// Created by Matt Bruce on 7/22/22.
//
import Foundation
import UIKit
import VDSColorTokens
import VDSFormControlsTokens
import Combine
public class Checkbox: CheckboxBase<DefaultCheckboxModel>{}
open class CheckboxBase<ModelType: CheckboxModel>: SelectorBase<ModelType> {
//--------------------------------------------------
// MARK: - Configuration Properties
//--------------------------------------------------
public let checkboxSize = CGSize(width: 20, height: 20)
private var checkboxBackgroundColorConfiguration: CheckboxErrorColorConfiguration = {
return CheckboxErrorColorConfiguration().with {
$0.forTrue.enabled.lightColor = VDSColor.elementsPrimaryOnlight
$0.forTrue.enabled.darkColor = VDSColor.elementsPrimaryOndark
$0.forTrue.disabled.lightColor = VDSColor.interactiveDisabledOnlight
$0.forTrue.disabled.darkColor = VDSColor.interactiveDisabledOndark
//error doesn't care enabled/disable
$0.error.forTrue.lightColor = VDSColor.elementsPrimaryOnlight
$0.error.forTrue.darkColor = VDSColor.elementsPrimaryOndark
$0.error.forFalse.lightColor = VDSColor.feedbackErrorBackgroundOnlight
$0.error.forFalse.darkColor = VDSColor.feedbackErrorBackgroundOndark
}
}()
private var checkboxBorderColorConfiguration: CheckboxErrorColorConfiguration = {
return CheckboxErrorColorConfiguration().with {
$0.forTrue.enabled.lightColor = VDSColor.elementsPrimaryOnlight
$0.forTrue.enabled.darkColor = VDSColor.elementsPrimaryOndark
$0.forFalse.enabled.lightColor = VDSFormControlsColor.borderOnlight
$0.forFalse.enabled.darkColor = VDSFormControlsColor.borderOndark
$0.forTrue.disabled.lightColor = VDSColor.interactiveDisabledOnlight
$0.forTrue.disabled.darkColor = VDSColor.interactiveDisabledOndark
$0.forFalse.disabled.lightColor = VDSColor.interactiveDisabledOnlight
$0.forFalse.disabled.darkColor = VDSColor.interactiveDisabledOndark
//error doesn't care enabled/disable
$0.error.forTrue.lightColor = VDSColor.elementsPrimaryOnlight
$0.error.forTrue.darkColor = VDSColor.elementsPrimaryOndark
$0.error.forFalse.lightColor = VDSColor.feedbackErrorOnlight
$0.error.forFalse.darkColor = VDSColor.feedbackErrorOndark
}
}()
private var checkboxCheckColorConfiguration: BinarySurfaceColorConfiguration<ModelType> = {
return BinarySurfaceColorConfiguration<ModelType>().with {
$0.forTrue.lightColor = VDSColor.elementsPrimaryOndark
$0.forTrue.darkColor = VDSColor.elementsPrimaryOnlight
}
}()
//--------------------------------------------------
// MARK: - Checkbox View
//--------------------------------------------------
/// Manages the appearance of the checkbox.
private var shapeLayer: CAShapeLayer?
open override func getSelectorSize() -> CGSize {
return checkboxSize
}
open override func updateSelector(_ viewModel: ModelType) {
//get the colors
let backgroundColor = checkboxBackgroundColorConfiguration.getColor(viewModel)
let borderColor = checkboxBorderColorConfiguration.getColor(viewModel)
let checkColor = checkboxCheckColorConfiguration.getColor(viewModel)
if let shapeLayer = shapeLayer, let sublayers = layer.sublayers, sublayers.contains(shapeLayer) {
shapeLayer.removeFromSuperlayer()
self.shapeLayer = nil
}
selectorView.backgroundColor = backgroundColor
selectorView.layer.borderColor = borderColor.cgColor
selectorView.layer.cornerRadius = 2.0
selectorView.layer.borderWidth = 1.0
if shapeLayer == nil {
let bounds = selectorView.bounds
let length = max(bounds.size.height, bounds.size.width)
guard length > 0.0, shapeLayer == nil else { return }
//draw the checkmark layer
let xInsetLeft = length * 0.25
let yInsetTop = length * 0.3
let innerWidth = length - (xInsetLeft + length * 0.25) // + Right X Inset
let innerHeight = length - (yInsetTop + length * 0.35) // + Bottom Y Inset
let startPoint = CGPoint(x: xInsetLeft, y: yInsetTop + (innerHeight / 2))
let pivotOffSet = CGPoint(x: xInsetLeft + (innerWidth * 0.33), y: yInsetTop + innerHeight)
let endOffset = CGPoint(x: xInsetLeft + innerWidth, y: yInsetTop)
let bezierPath = UIBezierPath()
bezierPath.move(to: startPoint)
bezierPath.addLine(to: pivotOffSet)
bezierPath.addLine(to: endOffset)
let shapeLayer = CAShapeLayer()
self.shapeLayer = shapeLayer
shapeLayer.frame = bounds
layer.addSublayer(shapeLayer)
shapeLayer.strokeColor = checkColor.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.path = bezierPath.cgPath
shapeLayer.lineJoin = .miter
shapeLayer.lineWidth = 2
CATransaction.withDisabledAnimations {
shapeLayer.strokeEnd = model.selected ? 1 : 0
}
}
}
//--------------------------------------------------
// MARK: - Color Class Configurations
//--------------------------------------------------
private class CheckboxErrorColorConfiguration: BinaryDisabledSurfaceColorConfiguration<ModelType> {
public let error = BinarySurfaceColorConfiguration<ModelType>()
override func getColor(_ viewModel: ModelType) -> UIColor {
//only show error is enabled and showError == true
let showErrorColor = !viewModel.disabled && viewModel.hasError
if showErrorColor {
return error.getColor(viewModel)
} else {
return super.getColor(viewModel)
}
}
}
}