updated control to take in generic class
updated toggle to include this and make a abstract class and new subclass Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
parent
482d3854a1
commit
49e84c5255
@ -7,8 +7,21 @@
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
open class VDSControl: UIControl, ViewProtocol {
|
||||
open class VDSControl<ModelType>: UIControl, Modelable, ViewProtocol {
|
||||
|
||||
@Published public var model: ModelType
|
||||
private var cancellable: AnyCancellable?
|
||||
|
||||
open func set(with model: ModelType) {
|
||||
self.model = model
|
||||
}
|
||||
|
||||
open func onStateChange(viewModel: ModelType) {
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -18,18 +31,14 @@ open class VDSControl: UIControl, ViewProtocol {
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: .zero)
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
public init() {
|
||||
required public init(with model: ModelType) {
|
||||
self.model = model
|
||||
super.init(frame: .zero)
|
||||
initialSetup()
|
||||
set(with: model)
|
||||
}
|
||||
|
||||
public required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
fatalError("Control does not support xib.")
|
||||
}
|
||||
|
||||
@ -42,6 +51,9 @@ open class VDSControl: UIControl, ViewProtocol {
|
||||
initialSetupPerformed = true
|
||||
setupView()
|
||||
}
|
||||
cancellable = $model.debounce(for: .seconds(ModelStateDebounce), scheduler: RunLoop.main).sink { [weak self] viewModel in
|
||||
self?.onStateChange(viewModel: viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
open func reset() {
|
||||
|
||||
@ -10,7 +10,8 @@ import UIKit
|
||||
import VDSColorTokens
|
||||
import Combine
|
||||
|
||||
open class VDSLabel: UILabel, Modelable {
|
||||
open class VDSLabel: UILabel, Modelable, Initable {
|
||||
|
||||
@Published public var model: VDSLabelModel = DefaultLabelModel()
|
||||
private var cancellable: AnyCancellable?
|
||||
|
||||
@ -30,10 +31,16 @@ open class VDSLabel: UILabel, Modelable {
|
||||
public var surface: Surface
|
||||
|
||||
//Initializers
|
||||
public convenience init() {
|
||||
required public convenience init() {
|
||||
self.init(frame: .zero)
|
||||
}
|
||||
|
||||
public required convenience init(with model: VDSLabelModel) {
|
||||
self.init()
|
||||
self.model = model
|
||||
set(with: model)
|
||||
}
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
setup()
|
||||
|
||||
@ -17,11 +17,22 @@ import Combine
|
||||
Container: The background of the toggle control.
|
||||
Knob: The circular indicator that slides on the container.
|
||||
*/
|
||||
@objcMembers open class VDSToggle: VDSControl, Modelable, Changable {
|
||||
|
||||
public typealias ModelType = VDSToggleModel
|
||||
@Published public var model: ModelType = DefaultToggleModel()
|
||||
private var cancellable: AnyCancellable?
|
||||
final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
public convenience init() {
|
||||
self.init(with: DefaultToggleModel())
|
||||
}
|
||||
|
||||
required public init(with model: ModelType) {
|
||||
super.init(with: model)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
@objcMembers open class VDSToggleBase<ModelType: VDSToggleModel>: VDSControl<ModelType>, Changable {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Properties
|
||||
@ -76,8 +87,8 @@ import Combine
|
||||
// MARK: - Static Properties
|
||||
//--------------------------------------------------
|
||||
// Sizes are from InVision design specs.
|
||||
public static var toggleSize = CGSize(width: 52, height: 24)
|
||||
public static var knobSize = CGSize(width: 20, height: 20)
|
||||
public let toggleSize = CGSize(width: 52, height: 24)
|
||||
public let knobSize = CGSize(width: 20, height: 20)
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
@ -103,7 +114,7 @@ import Combine
|
||||
@Proxy(\.model.surface)
|
||||
public var surface: Surface
|
||||
|
||||
@Proxy(\VDSToggle.model.on)
|
||||
@Proxy(\.model.on)
|
||||
open var isOn: Bool
|
||||
|
||||
open override var isEnabled: Bool {
|
||||
@ -128,29 +139,6 @@ import Combine
|
||||
private var toggleHeightConstraint: NSLayoutConstraint?
|
||||
private var toggleWidthConstraint: NSLayoutConstraint?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
public required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
setup()
|
||||
}
|
||||
|
||||
public convenience override init() {
|
||||
self.init(frame: .zero)
|
||||
setup()
|
||||
}
|
||||
|
||||
func setup() {
|
||||
cancellable = $model.debounce(for: .seconds(ModelStateDebounce), scheduler: RunLoop.main).sink { [weak self] viewModel in
|
||||
self?.onStateChange(viewModel: viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
//functions
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
@ -159,9 +147,6 @@ import Combine
|
||||
public override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
|
||||
let toggleSize = Self.toggleSize
|
||||
let knobSize = Self.knobSize
|
||||
|
||||
toggleHeightConstraint?.constant = toggleSize.height
|
||||
toggleWidthConstraint?.constant = toggleSize.width
|
||||
|
||||
@ -185,9 +170,6 @@ import Combine
|
||||
|
||||
addSubview(stackView)
|
||||
|
||||
let toggleSize = Self.toggleSize
|
||||
let knobSize = Self.knobSize
|
||||
|
||||
toggleHeightConstraint = toggleView.heightAnchor.constraint(equalToConstant: toggleSize.height)
|
||||
toggleHeightConstraint?.isActive = true
|
||||
|
||||
@ -209,10 +191,6 @@ import Combine
|
||||
knobView.topAnchor.constraint(greaterThanOrEqualTo: toggleView.topAnchor).isActive = true
|
||||
toggleView.bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true
|
||||
|
||||
//setup stackview
|
||||
if showText {
|
||||
stackView.addArrangedSubview(label)
|
||||
}
|
||||
ensureLabel()
|
||||
stackView.addArrangedSubview(toggleView)
|
||||
stackView.topAnchor.constraint(equalTo: topAnchor).isActive = true
|
||||
@ -310,14 +288,14 @@ import Combine
|
||||
|
||||
public func knobReformAnimation() {
|
||||
UIView.animate(withDuration: 0.1, animations: {
|
||||
self.knobWidthConstraint?.constant = Self.knobSize.width
|
||||
self.knobWidthConstraint?.constant = self.knobSize.width
|
||||
self.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
/// Follow the SwiftUI View paradigm
|
||||
/// - Parameter viewModel: state
|
||||
private func onStateChange(viewModel: ModelType) {
|
||||
open override func onStateChange(viewModel: ModelType) {
|
||||
let enabled = !viewModel.disabled
|
||||
|
||||
label.set(with: viewModel)
|
||||
@ -339,7 +317,7 @@ import Combine
|
||||
}
|
||||
self.knobTrailingConstraint?.isActive = true
|
||||
self.knobLeadingConstraint?.isActive = true
|
||||
self.knobWidthConstraint?.constant = Self.knobSize.width
|
||||
self.knobWidthConstraint?.constant = self.knobSize.width
|
||||
self.layoutIfNeeded()
|
||||
}
|
||||
|
||||
@ -374,9 +352,4 @@ import Combine
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
// MARK:- Modable
|
||||
open func set(with model: ModelType) {
|
||||
self.model = model
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,5 +12,6 @@ public let ModelStateDebounce = 0.02
|
||||
public protocol Modelable {
|
||||
associatedtype ModelType
|
||||
var model: ModelType { get set }
|
||||
init(with model: ModelType)
|
||||
func set(with model: ModelType)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user