diff --git a/VDS/Components/Checkbox/Checkbox.swift b/VDS/Components/Checkbox/Checkbox.swift index 630b97ce..fd08007a 100644 --- a/VDS/Components/Checkbox/Checkbox.swift +++ b/VDS/Components/Checkbox/Checkbox.swift @@ -89,10 +89,8 @@ open class Checkbox: Control, Errorable, Changeable { $0.textStyle = .bodyMedium } - open var selectorView = UIView().with { - $0.translatesAutoresizingMaskIntoConstraints = false - } - + open var selectorView = CheckboxView() + open var isAnimated: Bool = true { didSet { setNeedsUpdate() }} open override var isSelected: Bool { didSet { setNeedsUpdate() }} @@ -180,18 +178,7 @@ open class Checkbox: Control, Errorable, Changeable { selectorStackView.addArrangedSubview(selectorLabelStackView) selectorLabelStackView.addArrangedSubview(label) selectorLabelStackView.addArrangedSubview(childLabel) - - let selectorSize = getSelectorSize() - selectorHeightConstraint = selectorView.heightAnchor.constraint(equalToConstant: selectorSize.height) - selectorHeightConstraint?.isActive = true - - selectorWidthConstraint = selectorView.widthAnchor.constraint(equalToConstant: selectorSize.width) - selectorWidthConstraint?.isActive = true - - updateSelector() - mainStackView.pinToSuperView() - } func updateLabels() { @@ -292,66 +279,128 @@ open class Checkbox: Control, Errorable, Changeable { //-------------------------------------------------- open override func updateView() { updateLabels() - updateSelector() + selectorView.isAnimated = isAnimated + selectorView.showError = showError + selectorView.isSelected = isSelected updateAccessibilityLabel() } open override func updateAccessibilityLabel() { setAccessibilityLabel(for: [label, childLabel, errorLabel]) } +} + +public protocol SelectorControlable: Control, Changeable { + var showError: Bool { get set } + var size: CGSize { get set } + var backgroundColorConfig: ControlColorConfiguration { get set } + var borderColorConfig: ControlColorConfiguration { get set } + var selectorColorConfig: ControlColorConfiguration { get set } +} + +open class CheckboxView: Control, SelectorControlable { + public var onChangeSubscriber: AnyCancellable? + + open var isAnimated: Bool = true { didSet { setNeedsUpdate() }} + + open var size = CGSize(width: 20, height: 20) { didSet { setNeedsUpdate() }} + + var _showError: Bool = false + open var showError: Bool { + get { _showError } + set { + if !isSelected && _showError != newValue { + _showError = newValue + setNeedsUpdate() + } + } + } - //-------------------------------------------------- - // MARK: - Configuration Properties - //-------------------------------------------------- - public let checkboxSize = CGSize(width: 20, height: 20) - - private var backgroundColorConfig = ControlColorConfiguration().with { + open override var state: UIControl.State { + get { + var state = super.state + if showError { + state.insert(.error) + } + return state + } + } + + open var backgroundColorConfig = ControlColorConfiguration().with { $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: [.selected,.highlighted]) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: [.selected, .disabled]) $0.setSurfaceColors(VDSColor.feedbackErrorBackgroundOnlight, VDSColor.feedbackErrorBackgroundOndark, forState: .error) - } + }{ didSet { setNeedsUpdate() }} - private var borderColorConfig = ControlColorConfiguration().with { + open var borderColorConfig = ControlColorConfiguration().with { $0.setSurfaceColors(VDSFormControlsColor.borderOnlight, VDSFormControlsColor.borderOndark, forState: .normal) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .highlighted) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected) $0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error) - } + }{ didSet { setNeedsUpdate() }} - private var checkColorConfig = ControlColorConfiguration().with { + open var selectorColorConfig = ControlColorConfiguration().with { $0.setSurfaceColors(VDSColor.elementsPrimaryOndark, VDSColor.elementsPrimaryOnlight, forState: .selected) $0.setSurfaceColors(VDSColor.elementsPrimaryOndark, VDSColor.elementsPrimaryOnlight, forState: [.selected, .disabled]) $0.setSurfaceColors(VDSColor.elementsPrimaryOndark, VDSColor.elementsPrimaryOnlight, forState: [.selected, .highlighted]) - } - + }{ didSet { setNeedsUpdate() }} + //-------------------------------------------------- - // MARK: - Checkbox View + // MARK: - Constraints //-------------------------------------------------- - /// Manages the appearance of the checkbox. + private var selectorHeightConstraint: NSLayoutConstraint? + private var selectorWidthConstraint: NSLayoutConstraint? + private var shapeLayer: CAShapeLayer? + + open override func setup() { + super.setup() + let layoutGuide = UILayoutGuide() + addLayoutGuide(layoutGuide) + + selectorHeightConstraint = layoutGuide.heightAnchor.constraint(equalToConstant: size.height) + selectorHeightConstraint?.isActive = true + + selectorWidthConstraint = layoutGuide.widthAnchor.constraint(equalToConstant: size.width) + selectorWidthConstraint?.isActive = true + + NSLayoutConstraint.activate([ + layoutGuide.topAnchor.constraint(equalTo: topAnchor), + layoutGuide.bottomAnchor.constraint(equalTo: bottomAnchor), + layoutGuide.leadingAnchor.constraint(equalTo: leadingAnchor), + layoutGuide.trailingAnchor.constraint(equalTo: trailingAnchor)]) - open func getSelectorSize() -> CGSize { - return checkboxSize + layer.cornerRadius = 2.0 + layer.borderWidth = VDSFormControls.widthBorder + + } + open override func updateView() { + super.updateView() + + selectorHeightConstraint?.constant = size.height + selectorWidthConstraint?.constant = size.width + + setNeedsLayout() + layoutIfNeeded() } - open func updateSelector() { + open override func layoutSubviews() { + super.layoutSubviews() + //get the colors let backgroundColor = backgroundColorConfig.getColor(self) let borderColor = borderColorConfig.getColor(self) - let checkColor = checkColorConfig.getColor(self) + let checkColor = selectorColorConfig.getColor(self) if let shapeLayer = shapeLayer, let sublayers = layer.sublayers, sublayers.contains(shapeLayer) { shapeLayer.removeFromSuperlayer() self.shapeLayer = nil } - selectorView.layer.cornerRadius = VDSFormControls.borderradius - selectorView.layer.borderWidth = VDSFormControls.widthBorder - if shapeLayer == nil { - let bounds = selectorView.bounds + let bounds = bounds let length = max(bounds.size.height, bounds.size.width) guard length > 0.0, shapeLayer == nil else { return } @@ -397,16 +446,16 @@ open class Checkbox: Control, Errorable, Changeable { self.shapeLayer?.add(animateStrokeEnd, forKey: "strokeEnd") UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: { - self.selectorView.backgroundColor = backgroundColor - self.selectorView.layer.borderColor = borderColor.cgColor + self.backgroundColor = backgroundColor + self.layer.borderColor = borderColor.cgColor }) } else { CATransaction.withDisabledAnimations { self.shapeLayer?.strokeEnd = isSelected ? 1 : 0 } - selectorView.backgroundColor = backgroundColor - selectorView.layer.borderColor = borderColor.cgColor + self.backgroundColor = backgroundColor + layer.borderColor = borderColor.cgColor } } }