// // RadioButton.swift // VDS // // Created by Matt Bruce on 7/22/22. // import Foundation import UIKit import VDSColorTokens import VDSFormControlsTokens public class RadioButton: RadioButtonBase{} open class RadioButtonBase: SelectorBase { //-------------------------------------------------- // MARK: - Configuration Properties //-------------------------------------------------- public let radioButtonSize = CGSize(width: 20, height: 20) public let radioButtonSelectedSize = CGSize(width: 10, height: 10) private var radioButtonBackgroundColorConfiguration: RadioButtonErrorColorConfiguration = { return RadioButtonErrorColorConfiguration().with { //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 radioButtonBorderColorConfiguration: RadioButtonErrorColorConfiguration = { return RadioButtonErrorColorConfiguration().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 radioButtonCheckColorConfiguration: BinaryDisabledSurfaceColorConfiguration = { return BinaryDisabledSurfaceColorConfiguration().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 } }() open override func toggle() { guard !isSelected else { return } super.toggle() } //-------------------------------------------------- // MARK: - RadioButton View //-------------------------------------------------- /// Manages the appearance of the radioButton. private var shapeLayer: CAShapeLayer? open override func getSelectorSize() -> CGSize { return radioButtonSize } open override func updateSelector(_ viewModel: ModelType) { if let shapeLayer = shapeLayer, let sublayers = layer.sublayers, sublayers.contains(shapeLayer) { shapeLayer.removeFromSuperlayer() self.shapeLayer = nil } let bounds = selectorView.bounds let length = max(bounds.size.height, bounds.size.width) guard length > 0.0, shapeLayer == nil else { return } //get the colors let backgroundColor = radioButtonBackgroundColorConfiguration.getColor(viewModel) let borderColor = radioButtonBorderColorConfiguration.getColor(viewModel) let radioSelectedColor = radioButtonCheckColorConfiguration.getColor(viewModel) selectorView.backgroundColor = backgroundColor selectorView.layer.borderColor = borderColor.cgColor selectorView.layer.cornerRadius = selectorView.bounds.width * 0.5 selectorView.layer.borderWidth = 1.0 if shapeLayer == nil { let selectedBounds = radioButtonSelectedSize let bezierPath = UIBezierPath(ovalIn: CGRect(x: (bounds.width - selectedBounds.width) / 2, y: (bounds.height - selectedBounds.height) / 2, width: radioButtonSelectedSize.width, height: radioButtonSelectedSize.height)) let shapeLayer = CAShapeLayer() self.shapeLayer = shapeLayer shapeLayer.frame = bounds layer.addSublayer(shapeLayer) shapeLayer.fillColor = radioSelectedColor.cgColor shapeLayer.path = bezierPath.cgPath } } //-------------------------------------------------- // MARK: - Color Class Configurations //-------------------------------------------------- private class RadioButtonErrorColorConfiguration: BinaryDisabledSurfaceColorConfiguration { public let error = BinarySurfaceColorConfiguration() 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) } } } }