133 lines
4.1 KiB
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() }
|
|
}
|
|
}
|
|
|
|
|