// // RadioBoxGroup.swift // VDS // // Created by Matt Bruce on 8/23/22. // import Foundation import UIKit /// Radio boxes are single-select components through which a customer indicates a choice. /// They're stylized ``RadioButtons`` that must always be paired with one or more ``RadioBoxItem`` /// in a radio box group. Use radio boxes to display choices like device storage. @objc(VDSRadioBoxGroup) open class RadioBoxGroup: SelectorGroupBase, SelectorGroupSingleSelect { //-------------------------------------------------- // 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 //-------------------------------------------------- public var inputId: String? public var value: SelectorItemType? { selectedItem } /// Array of ``RadioBoxItemModel`` that will be used to build the selectorViews of type ``RadioBoxItem``. open var selectorModels: [RadioBoxItemModel]? { didSet { if let selectorModels { items = selectorModels.enumerated().map { index, model in return RadioBoxItem().with { $0.text = model.text $0.textAttributes = model.textAttributes $0.subText = model.subText $0.subTextAttributes = model.subTextAttributes $0.subTextRight = model.subTextRight $0.subTextRightAttributes = model.subTextRightAttributes $0.isEnabled = !model.disabled $0.inputId = model.inputId $0.hiddenValue = model.value $0.isSelected = model.selected $0.strikethrough = model.strikethrough $0.strikethroughAccessibilityText = model.strikethroughAccessibileText $0.selectorView.bridge_accessibilityValueBlock = { "item \(index+1) of \(selectorModels.count)" } } } } setNeedsUpdate() } } //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- private func ensureDevice() { if UIDevice.isIPad { mainStackView.axis = .horizontal mainStackView.distribution = .fillEqually } else { if UIDevice.current.orientation.isPortrait || UIDevice.current.orientation == .unknown { mainStackView.axis = .vertical mainStackView.distribution = .fill } else { mainStackView.axis = .horizontal mainStackView.distribution = .fillEqually } } } /// 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() ensureDevice() NotificationCenter.default .publisher(for: UIDevice.orientationDidChangeNotification) .sink() { [weak self] _ in UIView.animate(withDuration: 1.0) { self?.ensureDevice() } }.store(in: &subscribers) } open override func didSelect(_ selectedControl: RadioBoxItem) { let oldSelectedControl = items.filter { $0.isSelected == true }.first oldSelectedControl?.toggle() selectedControl.toggle() valueChanged() } } extension RadioBoxGroup { public struct RadioBoxItemModel: Surfaceable, Initable, FormFieldable { /// Whether this object is disabled or not public var disabled: Bool /// Current Surface and this is used to pass down to child objects that implement Surfacable public var surface: Surface public var inputId: String? public var value: String? public var accessibileText: String? public var text: String /// Array of LabelAttributeModel objects used in rendering the text. public var textAttributes: [any LabelAttributeModel]? public var subText: String? /// Array of LabelAttributeModel objects used in rendering the subText. public var subTextAttributes: [any LabelAttributeModel]? public var subTextRight: String? /// Array of LabelAttributeModel objects used in rendering the subTextRight. public var subTextRightAttributes: [any LabelAttributeModel]? public var selected: Bool public var strikethrough: Bool = false public var strikethroughAccessibileText: String public init(disabled: Bool, surface: Surface = .light, inputId: String? = nil, value: String? = nil, text: String = "", textAttributes: [any LabelAttributeModel]? = nil, subText: String? = nil, subTextAttributes: [any LabelAttributeModel]? = nil, subTextRight: String? = nil, subTextRightAttributes: [any LabelAttributeModel]? = nil, selected: Bool = false, errorText: String? = nil, accessibileText: String? = nil, strikethrough: Bool = false, strikethroughAccessibileText: String = "not available") { self.disabled = disabled self.surface = surface self.inputId = inputId self.value = value self.text = text self.textAttributes = textAttributes self.subText = subText self.subTextAttributes = subTextAttributes self.subTextRight = subTextRight self.subTextRightAttributes = subTextRightAttributes self.selected = selected self.accessibileText = accessibileText self.strikethrough = strikethrough self.strikethroughAccessibileText = strikethroughAccessibileText } public init() { self.init(disabled: false) } } }