vds_ios/VDS/BaseClasses/Selector/SelectorGroupBase.swift

133 lines
4.1 KiB
Swift

//
// SelectorGroupHandlerBase.swift
// VDS
//
// Created by Matt Bruce on 9/8/22.
//
import Foundation
import UIKit
import Combine
import VDSCoreTokens
public protocol SelectorGroup {
associatedtype SelectorItemType: Control
var items: [SelectorItemType] { get set }
var hasSelectedItem: Bool { get }
}
extension SelectorGroup {
public var hasSelectedItem: Bool { items.filter { $0.isSelected == true }.count > 0 }
}
public protocol SelectorGroupMultiSelect: SelectorGroup, FormFieldable {}
extension SelectorGroupMultiSelect {
/// Current Selected Control for this group.
public var selectedItems: [SelectorItemType]? {
let selected = items.filter{ $0.isSelected == true }
guard selected.count > 0 else { return nil }
return selected
}
}
public protocol SelectorGroupSingleSelect: SelectorGroup, FormFieldable {}
extension SelectorGroupSingleSelect {
/// Current Selected Control for this group.
public var selectedItem: SelectorItemType? {
return items.filter { $0.isSelected == true }.first
}
}
/// Base Class used for any Grouped Form Control of a Selector Type.
open class SelectorGroupBase<SelectorItemType: Control>: Control, SelectorGroup, Changeable {
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
open var mainStackView: UIStackView = {
return UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.alignment = .fill
$0.distribution = .fill
$0.axis = .vertical
$0.spacing = VDSLayout.space3X
}
}()
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
/// Array of the HandlerType registered.
/// Array of HandlerType that the user will have the ability to select from.
open var items: [SelectorItemType] = [] {
willSet {
mainStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
}
didSet {
for selector in items {
selector.onClick = { [weak self] handler in
self?.didSelect(handler)
self?.setNeedsUpdate()
}
mainStackView.addArrangedSubview(selector)
}
}
}
open var onChangeSubscriber: AnyCancellable?
/// Whether the Control is enabled or not.
override open var isEnabled: Bool {
didSet {
items.forEach { $0.isEnabled = isEnabled }
}
}
///The background tint that the component will be placed on. This will automatically adjust other elements as needed and takes light or dark
override open var surface: Surface {
didSet {
items.forEach { handler in
handler.surface = surface
}
}
}
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
/// 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()
addSubview(mainStackView)
mainStackView
.pinTop()
.pinLeading()
.pinTrailing()
.pinBottom(0, .defaultHigh)
}
/// Handler for the Group to override on a select event.
/// - Parameter selectedControl: Selected Control the user interacted.
open func didSelect(_ selectedControl: SelectorItemType) {
fatalError("Must override didSelect")
}
/// Helper method to execute the valueChanged event.
open func valueChanged() {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in
self?.sendActions(for: .valueChanged)
}
}
/// Resets to default settings.
open override func reset() {
super.reset()
onChange = nil
items.forEach{ $0.reset() }
}
}