// // 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 = { let config = RadioButtonErrorColorConfiguration() //error doesn't care enabled/disable config.error.forTrue.lightColor = VDSColor.elementsPrimaryOnlight config.error.forTrue.darkColor = VDSColor.elementsPrimaryOndark config.error.forFalse.lightColor = VDSColor.feedbackErrorBackgroundOnlight config.error.forFalse.darkColor = VDSColor.feedbackErrorBackgroundOndark return config }() private var radioButtonBorderColorConfiguration: RadioButtonErrorColorConfiguration = { let config = RadioButtonErrorColorConfiguration() config.forTrue.enabled.lightColor = VDSColor.elementsPrimaryOnlight config.forTrue.enabled.darkColor = VDSColor.elementsPrimaryOndark config.forFalse.enabled.lightColor = VDSFormControlsColor.borderOnlight config.forFalse.enabled.darkColor = VDSFormControlsColor.borderOndark config.forTrue.disabled.lightColor = VDSColor.interactiveDisabledOnlight config.forTrue.disabled.darkColor = VDSColor.interactiveDisabledOndark config.forFalse.disabled.lightColor = VDSColor.interactiveDisabledOnlight config.forFalse.disabled.darkColor = VDSColor.interactiveDisabledOndark //error doesn't care enabled/disable config.error.forTrue.lightColor = VDSColor.elementsPrimaryOnlight config.error.forTrue.darkColor = VDSColor.elementsPrimaryOndark config.error.forFalse.lightColor = VDSColor.feedbackErrorOnlight config.error.forFalse.darkColor = VDSColor.feedbackErrorOndark return config }() private var radioButtonCheckColorConfiguration: BinaryDisabledSurfaceColorConfiguration = { let config = BinaryDisabledSurfaceColorConfiguration() config.forTrue.enabled.lightColor = VDSColor.elementsPrimaryOnlight config.forTrue.enabled.darkColor = VDSColor.elementsPrimaryOndark config.forTrue.disabled.lightColor = VDSColor.interactiveDisabledOnlight config.forTrue.disabled.darkColor = VDSColor.interactiveDisabledOndark return config }() open override func toggleAndAction() { guard !isSelected else { return } super.toggleAndAction() } //-------------------------------------------------- // 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) } } } }