// // SelectorBase.swift // VDS // // Created by Matt Bruce on 6/5/23. // import Foundation import Combine import VDSColorTokens import VDSFormControlsTokens public protocol SelectorControlable: Control, Changeable { /// Whether not to show the error. var showError: Bool { get set } /// Size of the SelectorView. var size: CGSize { get set } /// Configuration for the Background Color based on Control State. var backgroundColorConfiguration: ControlColorConfiguration { get set } /// Configuration for the Border Color based on Control State. var borderColorConfiguration: ControlColorConfiguration { get set } /// Configuration for the Selector Color based on Control State. var selectorColorConfiguration: ControlColorConfiguration { get set } } /// Base Class used to build out a Selector control. open class SelectorBase: Control, SelectorControlable { //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- required public init() { super.init(frame: .zero) } public override init(frame: CGRect) { super.init(frame: .zero) } public required init?(coder: NSCoder) { super.init(coder: coder) } //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- open var onChangeSubscriber: AnyCancellable? { willSet { if let onChangeSubscriber { onChangeSubscriber.cancel() } } } open var size = CGSize(width: 20, height: 20) { didSet { setNeedsUpdate() } } var _showError: Bool = false /// Whether not to show the error. open var showError: Bool { get { _showError } set { if !isSelected && _showError != newValue { _showError = newValue setNeedsUpdate() } } } /// Override UIControl state to add the .error state if showError is true. open override var state: UIControl.State { get { var state = super.state if showError { state.insert(.error) } else { state.remove(.error) } return state } } open var backgroundColorConfiguration = ControlColorConfiguration() { didSet { setNeedsUpdate() } } open var borderColorConfiguration = ControlColorConfiguration() { didSet { setNeedsUpdate() } } open var selectorColorConfiguration = ControlColorConfiguration() { didSet { setNeedsUpdate() } } /// The natural size for the receiving view, considering only properties of the view itself. open override var intrinsicContentSize: CGSize { size } //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- private var selectorView = View() //-------------------------------------------------- // MARK: - Constraints //-------------------------------------------------- internal var shapeLayer: CAShapeLayer? //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- /// Executed on initialization for this View. open override func initialSetup() { super.initialSetup() onClick = { control in control.toggle() } } /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. open override func setup() { super.setup() isAccessibilityElement = true accessibilityTraits = .button } /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { super.updateView() setNeedsLayout() layoutIfNeeded() } /// Used to update any Accessibility properties.ß open override func updateAccessibility() { super.updateAccessibility() } /// This will change the state of the Selector and execute the actionBlock if provided. open func toggle() { } }