Merge branch 'bugfix/setNeedsUpdate' into 'develop'
Big Refactor See merge request BPHV_MIPS/vds_ios!65
This commit is contained in:
commit
e5425d60b4
@ -100,7 +100,6 @@
|
||||
EAF1FE9B29DB1A6000101452 /* Changeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1FE9A29DB1A6000101452 /* Changeable.swift */; };
|
||||
EAF7F0952899861000B287F5 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0932899861000B287F5 /* Checkbox.swift */; };
|
||||
EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0992899B17200B287F5 /* CATransaction.swift */; };
|
||||
EAF7F09E289AAEC000B287F5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F09D289AAEC000B287F5 /* Constants.swift */; };
|
||||
EAF7F0A0289AB7EC00B287F5 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F09F289AB7EC00B287F5 /* View.swift */; };
|
||||
EAF7F0A2289AFB3900B287F5 /* Errorable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0A1289AFB3900B287F5 /* Errorable.swift */; };
|
||||
EAF7F0A4289B017C00B287F5 /* LabelAttributeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0A3289B017C00B287F5 /* LabelAttributeModel.swift */; };
|
||||
@ -221,7 +220,6 @@
|
||||
EAF1FE9A29DB1A6000101452 /* Changeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Changeable.swift; sourceTree = "<group>"; };
|
||||
EAF7F0932899861000B287F5 /* Checkbox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = "<group>"; };
|
||||
EAF7F0992899B17200B287F5 /* CATransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CATransaction.swift; sourceTree = "<group>"; };
|
||||
EAF7F09D289AAEC000B287F5 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
EAF7F09F289AB7EC00B287F5 /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = "<group>"; };
|
||||
EAF7F0A1289AFB3900B287F5 /* Errorable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Errorable.swift; sourceTree = "<group>"; };
|
||||
EAF7F0A3289B017C00B287F5 /* LabelAttributeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeModel.swift; sourceTree = "<group>"; };
|
||||
@ -447,7 +445,6 @@
|
||||
children = (
|
||||
EA985C1C296CD13600F2FF2E /* BundleManager.swift */,
|
||||
EAF7F0B8289C139800B287F5 /* ColorConfiguration.swift */,
|
||||
EAF7F09D289AAEC000B287F5 /* Constants.swift */,
|
||||
EA3361B5288B2A410071C351 /* Control.swift */,
|
||||
EAF7F09F289AB7EC00B287F5 /* View.swift */,
|
||||
EA4DB18428CA967F00103EE3 /* SelectorGroupHandlerBase.swift */,
|
||||
@ -853,7 +850,6 @@
|
||||
44604AD729CE196600E62B51 /* Line.swift in Sources */,
|
||||
EA5E3058295105A40082B959 /* Tilelet.swift in Sources */,
|
||||
EA89201528B56CF4006B9984 /* RadioBoxGroup.swift in Sources */,
|
||||
EAF7F09E289AAEC000B287F5 /* Constants.swift in Sources */,
|
||||
EA985C1D296CD13600F2FF2E /* BundleManager.swift in Sources */,
|
||||
EA1F266528B945070033E859 /* RadioSwatch.swift in Sources */,
|
||||
EA4DB18528CA967F00103EE3 /* SelectorGroupHandlerBase.swift in Sources */,
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
//
|
||||
// VDSConstants.swift
|
||||
// VDS
|
||||
//
|
||||
// Created by Matt Bruce on 8/3/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Constants {
|
||||
public static let StateDebounce = 0.0 //.001
|
||||
public static let PaddingOne = 10.0
|
||||
}
|
||||
@ -15,7 +15,6 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
|
||||
//--------------------------------------------------
|
||||
// MARK: - Combine Properties
|
||||
//--------------------------------------------------
|
||||
public var subject = PassthroughSubject<Void, Never>()
|
||||
public var subscribers = Set<AnyCancellable>()
|
||||
public var onClickSubscriber: AnyCancellable? {
|
||||
willSet {
|
||||
@ -30,13 +29,15 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
|
||||
//--------------------------------------------------
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
open var shouldUpdateView: Bool = true
|
||||
|
||||
open var userInfo = [String: Primitive]()
|
||||
|
||||
open var surface: Surface = .light { didSet { didChange() } }
|
||||
open var surface: Surface = .light { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var disabled: Bool = false { didSet { isEnabled = !disabled } }
|
||||
|
||||
open override var isSelected: Bool { didSet { didChange() } }
|
||||
open override var isSelected: Bool { didSet { setNeedsUpdate() } }
|
||||
|
||||
public var touchUpInsideCount: Int = 0
|
||||
|
||||
@ -65,7 +66,7 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
|
||||
disabled = !newValue
|
||||
}
|
||||
isUserInteractionEnabled = isEnabled
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,8 +96,7 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
|
||||
if !initialSetupPerformed {
|
||||
initialSetupPerformed = true
|
||||
setup()
|
||||
setupDidChangeEvent()
|
||||
updateView()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ open class SelectorGroupHandlerBase<HandlerType: Control>: Control, Changeable {
|
||||
}
|
||||
|
||||
public func valueChanged() {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + Constants.StateDebounce) { [weak self] in
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in
|
||||
self?.sendActions(for: .valueChanged)
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@ open class View: UIView, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Combine Properties
|
||||
//--------------------------------------------------
|
||||
public var subject = PassthroughSubject<Void, Never>()
|
||||
public var subscribers = Set<AnyCancellable>()
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -24,9 +23,11 @@ open class View: UIView, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
||||
//--------------------------------------------------
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
open var shouldUpdateView: Bool = true
|
||||
|
||||
open var userInfo = [String: Primitive]()
|
||||
|
||||
open var surface: Surface = .light { didSet { didChange() }}
|
||||
open var surface: Surface = .light { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var disabled: Bool = false { didSet { isEnabled = !disabled } }
|
||||
|
||||
@ -37,7 +38,7 @@ open class View: UIView, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
||||
disabled = !newValue
|
||||
}
|
||||
isUserInteractionEnabled = isEnabled
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,8 +68,7 @@ open class View: UIView, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
||||
if !initialSetupPerformed {
|
||||
initialSetupPerformed = true
|
||||
setup()
|
||||
setupDidChangeEvent()
|
||||
updateView()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -32,13 +32,13 @@ open class Badge: View {
|
||||
$0.textStyle = .boldBodySmall
|
||||
}
|
||||
|
||||
open var fillColor: FillColor = .red { didSet { didChange() }}
|
||||
open var fillColor: FillColor = .red { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var text: String = "" { didSet { didChange() }}
|
||||
open var text: String = "" { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var maxWidth: CGFloat? { didSet { didChange() }}
|
||||
open var maxWidth: CGFloat? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var numberOfLines: Int = 1 { didSet { didChange() }}
|
||||
open var numberOfLines: Int = 1 { didSet { setNeedsUpdate() }}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
@ -66,16 +66,18 @@ open class Badge: View {
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
super.reset()
|
||||
shouldUpdateView = false
|
||||
label.reset()
|
||||
label.lineBreakMode = .byTruncatingTail
|
||||
label.textPosition = .left
|
||||
label.textStyle = .boldBodySmall
|
||||
|
||||
fillColor = .red
|
||||
text = ""
|
||||
maxWidth = nil
|
||||
numberOfLines = 1
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -32,11 +32,11 @@ open class Button: ButtonBase, Useable {
|
||||
//--------------------------------------------------
|
||||
open override var availableSizes: [ButtonSize] { [.large, .small] }
|
||||
|
||||
open var use: Use = .primary { didSet { didChange() }}
|
||||
open var use: Use = .primary { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var size: ButtonSize = .large { didSet { didChange() }}
|
||||
open var size: ButtonSize = .large { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var width: CGFloat? { didSet { didChange() }}
|
||||
open var width: CGFloat? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open override var textColor: UIColor {
|
||||
textColorConfiguration.getColor(self)
|
||||
@ -132,9 +132,12 @@ open class Button: ButtonBase, Useable {
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
shouldUpdateView = false
|
||||
use = .primary
|
||||
width = nil
|
||||
size = .large
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -28,7 +28,6 @@ open class ButtonBase: UIButton, Buttonable, Handlerable, ViewProtocol, Resettab
|
||||
//--------------------------------------------------
|
||||
// MARK: - Combine Properties
|
||||
//--------------------------------------------------
|
||||
public var subject = PassthroughSubject<Void, Never>()
|
||||
public var subscribers = Set<AnyCancellable>()
|
||||
public var onClickSubscriber: AnyCancellable? {
|
||||
willSet {
|
||||
@ -46,13 +45,15 @@ open class ButtonBase: UIButton, Buttonable, Handlerable, ViewProtocol, Resettab
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
open var shouldUpdateView: Bool = true
|
||||
|
||||
open var availableSizes: [ButtonSize] { [] }
|
||||
|
||||
open var text: String? { didSet { didChange() } }
|
||||
open var text: String? { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var attributes: [any LabelAttributeModel]? { nil }
|
||||
|
||||
open var surface: Surface = .light { didSet { didChange() }}
|
||||
open var surface: Surface = .light { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var disabled: Bool = false { didSet { isEnabled = !disabled } }
|
||||
|
||||
@ -90,7 +91,7 @@ open class ButtonBase: UIButton, Buttonable, Handlerable, ViewProtocol, Resettab
|
||||
disabled = !newValue
|
||||
}
|
||||
isUserInteractionEnabled = isEnabled
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,8 +122,7 @@ open class ButtonBase: UIButton, Buttonable, Handlerable, ViewProtocol, Resettab
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
accessibilityCustomActions = []
|
||||
setup()
|
||||
setupDidChangeEvent(true)
|
||||
updateView()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,10 +136,13 @@ open class ButtonBase: UIButton, Buttonable, Handlerable, ViewProtocol, Resettab
|
||||
}
|
||||
|
||||
open func reset() {
|
||||
shouldUpdateView = false
|
||||
surface = .light
|
||||
disabled = false
|
||||
text = nil
|
||||
accessibilityCustomActions = []
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -25,16 +25,16 @@ open class ButtonGroup: View, UICollectionViewDataSource, UICollectionViewDelega
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
//An object containing number of Button components per row, in each viewport
|
||||
open var rowQuantityPhone: Int = 0 { didSet { didChange() } }
|
||||
open var rowQuantityPhone: Int = 0 { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var rowQuantityTablet: Int = 0 { didSet { didChange() } }
|
||||
open var rowQuantityTablet: Int = 0 { didSet { setNeedsUpdate() } }
|
||||
|
||||
public var rowQuantity: Int { UIDevice.isIPad ? rowQuantityTablet : rowQuantityPhone }
|
||||
|
||||
//If provided, aligns TextLink/TextLinkCaret alignment when rowQuantity is set one.
|
||||
open var buttonPosition: ButtonPosition = .center { didSet { didChange() }}
|
||||
open var buttonPosition: ButtonPosition = .center { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var buttons: [Buttonable] = [] { didSet { didChange() }}
|
||||
open var buttons: [Buttonable] = [] { didSet { setNeedsUpdate() }}
|
||||
|
||||
//If provided, width of Button components will be rendered based on this value. If omitted, default button widths are rendered.
|
||||
open var buttonWidth: CGFloat? {
|
||||
@ -47,7 +47,7 @@ open class ButtonGroup: View, UICollectionViewDataSource, UICollectionViewDelega
|
||||
button.width = buttonWidth
|
||||
}
|
||||
}
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ open class ButtonGroup: View, UICollectionViewDataSource, UICollectionViewDelega
|
||||
self.buttonWidth = nil
|
||||
}
|
||||
positionLayout.buttonPercentage = buttonPercentage
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ open class TextLink: ButtonBase {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
open var size: ButtonSize = .large { didSet { didChange() }}
|
||||
open var size: ButtonSize = .large { didSet { setNeedsUpdate() }}
|
||||
|
||||
open override var availableSizes: [ButtonSize] { [.large, .small] }
|
||||
|
||||
@ -88,10 +88,14 @@ open class TextLink: ButtonBase {
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
shouldUpdateView = false
|
||||
text = nil
|
||||
size = .large
|
||||
accessibilityCustomActions = []
|
||||
isAccessibilityElement = true
|
||||
accessibilityTraits = .link
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -28,11 +28,7 @@ open class TextLinkCaret: ButtonBase {
|
||||
TextStyle.boldBodyLarge
|
||||
}
|
||||
|
||||
private var caretView = CaretView().with {
|
||||
$0.size = CaretView.Size.small(.vertical)
|
||||
$0.lineWidth = 2
|
||||
}
|
||||
private var imageAttribute: ImageLabelAttribute?
|
||||
private var imageAttribute: ImageSpaceLabelAttribute?
|
||||
|
||||
open override var attributes: [any LabelAttributeModel]? {
|
||||
guard let imageAttribute else { return nil }
|
||||
@ -44,24 +40,12 @@ open class TextLinkCaret: ButtonBase {
|
||||
//--------------------------------------------------
|
||||
public override var availableSizes: [ButtonSize] { [.large] }
|
||||
|
||||
open var iconPosition: IconPosition = .right { didSet { didChange() } }
|
||||
open var iconPosition: IconPosition = .right { didSet { setNeedsUpdate() } }
|
||||
|
||||
private var height: CGFloat {
|
||||
44
|
||||
}
|
||||
|
||||
private var _text: String?
|
||||
|
||||
open override var text: String? {
|
||||
get{ _text }
|
||||
set {
|
||||
var updatedText = newValue ?? ""
|
||||
updatedText = iconPosition == .right ? "\(updatedText) " : " \(updatedText)"
|
||||
_text = updatedText
|
||||
didChange()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
open override var textColor: UIColor {
|
||||
textColorConfiguration.getColor(self)
|
||||
}
|
||||
@ -92,14 +76,12 @@ open class TextLinkCaret: ButtonBase {
|
||||
//--------------------------------------------------
|
||||
open override func setup() {
|
||||
super.setup()
|
||||
|
||||
let size = caretView.size!.dimensions()
|
||||
caretView.frame = .init(x: 0, y: 0, width: size.width, height: size.height)
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
iconPosition = .right
|
||||
text = nil
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -111,204 +93,53 @@ open class TextLinkCaret: ButtonBase {
|
||||
|
||||
var itemWidth = size.width
|
||||
|
||||
if let caretWidth = caretView.size?.dimensions().width {
|
||||
if let caretWidth = imageAttribute?.width {
|
||||
itemWidth += caretWidth
|
||||
}
|
||||
return CGSize(width: itemWidth, height: size.height)
|
||||
}
|
||||
|
||||
open override func updateView() {
|
||||
|
||||
let updatedText = text ?? ""
|
||||
caretView.surface = surface
|
||||
caretView.disabled = disabled
|
||||
caretView.direction = iconPosition == .right ? CaretView.Direction.right : CaretView.Direction.left
|
||||
|
||||
let image = caretView.getImage()
|
||||
let location = iconPosition == .right ? updatedText.count : 0
|
||||
|
||||
imageAttribute = ImageLabelAttribute(location: location,
|
||||
image: image,
|
||||
tintColor: textColor)
|
||||
|
||||
imageAttribute = ImageSpaceLabelAttribute(tintColor: textColor, position: iconPosition)
|
||||
super.updateView()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension UIView {
|
||||
public func getImage() -> UIImage {
|
||||
let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
|
||||
let image = renderer.image { ctx in
|
||||
self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
|
||||
}
|
||||
return image
|
||||
}
|
||||
}
|
||||
extension TextLinkCaret {
|
||||
struct ImageSpaceLabelAttribute: LabelAttributeModel {
|
||||
var id: UUID = .init()
|
||||
var location: Int = 0
|
||||
var length: Int = 1
|
||||
var tintColor: UIColor
|
||||
var position: IconPosition
|
||||
var spacerWidth: CGFloat = 2.0
|
||||
var width: CGFloat { caretSize.width + spacerWidth }
|
||||
var caretSize: CGSize { Icon.Size.xsmall.dimensions }
|
||||
|
||||
internal class CaretView: View {
|
||||
//------------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//------------------------------------------------------
|
||||
private var caretPath: UIBezierPath = UIBezierPath()
|
||||
|
||||
public var lineWidth: CGFloat = 1 { didSet{ didChange() } }
|
||||
|
||||
public var direction: Direction = .right { didSet{ didChange() } }
|
||||
|
||||
public var size: Size? { didSet{ didChange() } }
|
||||
|
||||
public var colorConfiguration: AnyColorable = ViewColorConfiguration().with {
|
||||
$0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forDisabled: true)
|
||||
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false)
|
||||
}.eraseToAnyColorable()
|
||||
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//------------------------------------------------------
|
||||
|
||||
/// Sizes of CaretView are derived from InVision design specs. They are provided for convenience.
|
||||
public enum Size {
|
||||
case small(Orientation)
|
||||
case medium(Orientation)
|
||||
case large(Orientation)
|
||||
|
||||
/// Orientation based on the longest line of the view.
|
||||
public enum Orientation {
|
||||
case vertical
|
||||
case horizontal
|
||||
init(tintColor: UIColor, position: IconPosition) {
|
||||
self.tintColor = tintColor
|
||||
self.position = position
|
||||
}
|
||||
|
||||
/// Dimensions of container; provided by InVision design.
|
||||
func dimensions() -> CGSize {
|
||||
func setAttribute(on attributedString: NSMutableAttributedString) {
|
||||
let imageAttr = ImageLabelAttribute(location: location, imageName: "\(position.rawValue)-caret-bold", frame: .init(x: 0, y: 0, width: caretSize.width, height: caretSize.height), tintColor: tintColor)
|
||||
let spaceAttr = ImageLabelAttribute(location: 0, imageName: "info", frame: .init(x: 0, y: 0, width: spacerWidth, height: 5.0), tintColor: .clear)
|
||||
|
||||
switch self {
|
||||
case .small(let o):
|
||||
return o == .vertical ? CGSize(width: 6.9, height: 10.96) : CGSize(width: 10.96, height: 6.9)
|
||||
|
||||
case .medium(let o):
|
||||
return o == .vertical ? CGSize(width: 9.9, height: 16.96) : CGSize(width: 16.96, height: 9.9)
|
||||
|
||||
case .large(let o):
|
||||
return o == .vertical ? CGSize(width: 14.9, height: 24.96) : CGSize(width: 24.96, height: 14.9)
|
||||
guard let image = try? imageAttr.getAttachment(),
|
||||
let spacer = try? spaceAttr.getAttachment() else { return }
|
||||
|
||||
if position == .right {
|
||||
attributedString.append(NSAttributedString(attachment: spacer))
|
||||
attributedString.append(NSAttributedString(attachment: image))
|
||||
} else {
|
||||
attributedString.insert(NSAttributedString(attachment: image), at: 0)
|
||||
attributedString.insert(NSAttributedString(attachment: spacer), at: 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Initialization
|
||||
//------------------------------------------------------
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
}
|
||||
|
||||
public convenience init(lineWidth: CGFloat) {
|
||||
self.init(frame: .zero)
|
||||
self.lineWidth = lineWidth
|
||||
}
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
fatalError("CaretView xib not supported.")
|
||||
}
|
||||
|
||||
required public convenience init() {
|
||||
self.init(frame: .zero)
|
||||
}
|
||||
|
||||
public convenience init(size: Size){
|
||||
let dimensions = size.dimensions()
|
||||
self.init(frame: .init(x: 0, y: 0, width: dimensions.width, height: dimensions.height))
|
||||
self.size = size
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Setup
|
||||
//------------------------------------------------------
|
||||
|
||||
override open func setup() {
|
||||
super.setup()
|
||||
defaultState()
|
||||
|
||||
isAccessibilityElement = true
|
||||
accessibilityTraits = .link
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Drawing
|
||||
//------------------------------------------------------
|
||||
|
||||
/// The direction the caret will be pointing to.
|
||||
public enum Direction: Int {
|
||||
case left
|
||||
case right
|
||||
case down
|
||||
case up
|
||||
}
|
||||
|
||||
override func draw(_ rect: CGRect) {
|
||||
super.draw(rect)
|
||||
|
||||
caretPath.removeAllPoints()
|
||||
caretPath.lineJoinStyle = .miter
|
||||
caretPath.lineWidth = lineWidth
|
||||
|
||||
let inset = lineWidth / 2
|
||||
let halfWidth = frame.size.width / 2
|
||||
let halfHeight = frame.size.height / 2
|
||||
|
||||
switch direction {
|
||||
case .up:
|
||||
caretPath.move(to: CGPoint(x: inset, y: frame.size.height - inset))
|
||||
caretPath.addLine(to: CGPoint(x: halfWidth, y: inset))
|
||||
caretPath.addLine(to: CGPoint(x: frame.size.width, y: frame.size.height))
|
||||
|
||||
case .right:
|
||||
caretPath.move(to: CGPoint(x: inset, y: inset))
|
||||
caretPath.addLine(to: CGPoint(x: frame.size.width - inset, y: halfHeight))
|
||||
caretPath.addLine(to: CGPoint(x: inset, y: frame.size.height - inset))
|
||||
|
||||
case .down:
|
||||
caretPath.move(to: CGPoint(x: inset, y: inset))
|
||||
caretPath.addLine(to: CGPoint(x: halfWidth, y: frame.size.height - inset))
|
||||
caretPath.addLine(to: CGPoint(x: frame.size.width - inset, y: inset))
|
||||
|
||||
case .left:
|
||||
caretPath.move(to: CGPoint(x: frame.size.width - inset, y: inset))
|
||||
caretPath.addLine(to: CGPoint(x: inset, y: halfHeight))
|
||||
caretPath.addLine(to: CGPoint(x: frame.size.width - inset, y: frame.size.height - inset))
|
||||
func isEqual(_ equatable: ImageSpaceLabelAttribute) -> Bool {
|
||||
return id == equatable.id && range == equatable.range
|
||||
}
|
||||
|
||||
let color = colorConfiguration.getColor(self)
|
||||
color.setStroke()
|
||||
caretPath.stroke()
|
||||
}
|
||||
|
||||
override func updateView() {
|
||||
setNeedsDisplay()
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//------------------------------------------------------
|
||||
public func setLineColor(_ color: UIColor) {
|
||||
setNeedsDisplay()
|
||||
}
|
||||
|
||||
public func defaultState() {
|
||||
isOpaque = false
|
||||
isHidden = false
|
||||
backgroundColor = .clear
|
||||
}
|
||||
|
||||
/// Ensure you have defined a CaretSize with Orientation before calling.
|
||||
public func setConstraints() {
|
||||
|
||||
guard let dimensions = size?.dimensions() else { return }
|
||||
|
||||
heightAnchor.constraint(equalToConstant: dimensions.height).isActive = true
|
||||
widthAnchor.constraint(equalToConstant: dimensions.width).isActive = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,31 +93,31 @@ open class Checkbox: Control, Errorable, Changeable {
|
||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
open var isAnimated: Bool = true { didSet { didChange() }}
|
||||
open var isAnimated: Bool = true { didSet { setNeedsUpdate() }}
|
||||
|
||||
open override var isSelected: Bool { didSet { didChange() }}
|
||||
open override var isSelected: Bool { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var labelText: String? { didSet { didChange() }}
|
||||
open var labelText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var labelTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
|
||||
open var labelTextAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var labelAttributedText: NSAttributedString? {
|
||||
didSet {
|
||||
label.useAttributedText = !(labelAttributedText?.string.isEmpty ?? true)
|
||||
label.attributedText = labelAttributedText
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
open var childText: String? { didSet { didChange() }}
|
||||
open var childText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var childTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
|
||||
open var childTextAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var childAttributedText: NSAttributedString? {
|
||||
didSet {
|
||||
childLabel.useAttributedText = !(childAttributedText?.string.isEmpty ?? true)
|
||||
childLabel.attributedText = childAttributedText
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ open class Checkbox: Control, Errorable, Changeable {
|
||||
set {
|
||||
if !isSelected && _showError != newValue {
|
||||
_showError = newValue
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,11 +142,11 @@ open class Checkbox: Control, Errorable, Changeable {
|
||||
}
|
||||
}
|
||||
|
||||
open var errorText: String? { didSet { didChange() }}
|
||||
open var errorText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var inputId: String? { didSet { didChange() }}
|
||||
open var inputId: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var value: AnyHashable? { didSet { didChange() }}
|
||||
open var value: AnyHashable? { didSet { setNeedsUpdate() }}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
@ -252,6 +252,7 @@ open class Checkbox: Control, Errorable, Changeable {
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
shouldUpdateView = false
|
||||
label.reset()
|
||||
childLabel.reset()
|
||||
errorLabel.reset()
|
||||
@ -272,7 +273,8 @@ open class Checkbox: Control, Errorable, Changeable {
|
||||
value = nil
|
||||
isSelected = false
|
||||
|
||||
updateSelector()
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
/// This will checkbox the state of the Selector and execute the actionBlock if provided.
|
||||
@ -384,7 +386,7 @@ open class Checkbox: Control, Errorable, Changeable {
|
||||
|
||||
shapeLayer?.removeAllAnimations()
|
||||
|
||||
if isAnimated {
|
||||
if isAnimated && !disabled {
|
||||
let animateStrokeEnd = CABasicAnimation(keyPath: "strokeEnd")
|
||||
animateStrokeEnd.timingFunction = CAMediaTimingFunction(name: .linear)
|
||||
animateStrokeEnd.duration = 0.3
|
||||
|
||||
@ -28,10 +28,10 @@ open class Icon: View {
|
||||
$0.clipsToBounds = true
|
||||
}
|
||||
|
||||
open var color: Color = .black { didSet { didChange() }}
|
||||
open var size: Size = .medium { didSet { didChange() }}
|
||||
open var name: Name? { didSet { didChange() }}
|
||||
open var customSize: Int? { didSet { didChange() }}
|
||||
open var color: Color = .black { didSet { setNeedsUpdate() }}
|
||||
open var size: Size = .medium { didSet { setNeedsUpdate() }}
|
||||
open var name: Name? { didSet { setNeedsUpdate() }}
|
||||
open var customSize: Int? { didSet { setNeedsUpdate() }}
|
||||
|
||||
//functions
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -72,7 +72,7 @@ public class TooltipLabelAttribute: ActionLabelAttributeModel, TooltipLaunchable
|
||||
addHandler(on: attributedString)
|
||||
}
|
||||
|
||||
public init(id: UUID = UUID(), action: PassthroughSubject<Void, Never> = PassthroughSubject<Void, Never>(), subscriber: AnyCancellable? = nil, surface: Surface, accessibleText: String? = nil, closeButtonText: String, title: String, content: String) {
|
||||
public init(id: UUID = UUID(), action: PassthroughSubject<Void, Never> = PassthroughSubject<Void, Never>(), subscriber: AnyCancellable? = nil, surface: Surface, accessibleText: String? = nil, closeButtonText: String = "Close", title: String, content: String) {
|
||||
self.id = id
|
||||
self.action = action
|
||||
self.subscriber = subscriber
|
||||
|
||||
@ -16,26 +16,26 @@ open class Label: UILabel, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Combine Properties
|
||||
//--------------------------------------------------
|
||||
public var subject = PassthroughSubject<Void, Never>()
|
||||
public var subscribers = Set<AnyCancellable>()
|
||||
public var hasChanged: Bool = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
open var shouldUpdateView: Bool = true
|
||||
|
||||
open var useAttributedText: Bool = false
|
||||
|
||||
open var surface: Surface = .light { didSet { didChange() }}
|
||||
open var surface: Surface = .light { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var disabled: Bool = false { didSet { isEnabled = !disabled } }
|
||||
|
||||
open var attributes: [any LabelAttributeModel]? { didSet { didChange() }}
|
||||
open var attributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var textStyle: TextStyle = .defaultStyle { didSet { didChange() }}
|
||||
open var textStyle: TextStyle = .defaultStyle { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var textPosition: TextPosition = .left { didSet { didChange() }}
|
||||
open var textPosition: TextPosition = .left { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var userInfo = [String: Primitive]()
|
||||
|
||||
@ -46,14 +46,14 @@ open class Label: UILabel, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
||||
disabled = !newValue
|
||||
}
|
||||
isUserInteractionEnabled = isEnabled
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
override open var text: String? {
|
||||
didSet {
|
||||
attributes = nil
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,14 +95,14 @@ open class Label: UILabel, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
||||
accessibilityCustomActions = []
|
||||
accessibilityTraits = .staticText
|
||||
setup()
|
||||
setupDidChangeEvent(true)
|
||||
updateView()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
open func setup() {}
|
||||
|
||||
open func reset() {
|
||||
shouldUpdateView = false
|
||||
surface = .light
|
||||
disabled = false
|
||||
attributes = nil
|
||||
@ -112,6 +112,8 @@ open class Label: UILabel, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
||||
attributedText = nil
|
||||
numberOfLines = 0
|
||||
backgroundColor = .clear
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -26,7 +26,7 @@ open class Line: View {
|
||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
open var style: Style = .primary { didSet { didChange() } }
|
||||
open var style: Style = .primary { didSet { setNeedsUpdate() } }
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
|
||||
@ -117,18 +117,18 @@ open class Notification: View {
|
||||
}
|
||||
|
||||
//Text
|
||||
open var title: String = "" { didSet{didChange()}}
|
||||
open var title: String = "" { didSet{setNeedsUpdate()}}
|
||||
|
||||
open var subTitle: String? { didSet{didChange()}}
|
||||
open var subTitle: String? { didSet{setNeedsUpdate()}}
|
||||
|
||||
//Buttons
|
||||
open var primaryButtonModel: ButtonModel? { didSet{didChange()}}
|
||||
open var primaryButtonModel: ButtonModel? { didSet{setNeedsUpdate()}}
|
||||
open var primaryButton = Button().with {
|
||||
$0.size = .small
|
||||
$0.use = .secondary
|
||||
}
|
||||
|
||||
open var secondaryButtonModel: ButtonModel? { didSet{didChange()}}
|
||||
open var secondaryButtonModel: ButtonModel? { didSet{setNeedsUpdate()}}
|
||||
open var secondaryButton = Button().with {
|
||||
$0.size = .small
|
||||
$0.use = .secondary
|
||||
@ -152,11 +152,11 @@ open class Notification: View {
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
open var hideCloseButton: Bool = false { didSet{didChange()}}
|
||||
open var hideCloseButton: Bool = false { didSet{setNeedsUpdate()}}
|
||||
|
||||
open var type: Style = .info { didSet{didChange()}}
|
||||
open var type: Style = .info { didSet{setNeedsUpdate()}}
|
||||
|
||||
open var fullBleed: Bool = false { didSet {didChange()}}
|
||||
open var fullBleed: Bool = false { didSet {setNeedsUpdate()}}
|
||||
|
||||
var _layout: Layout = .vertical
|
||||
open var layout: Layout {
|
||||
@ -164,7 +164,7 @@ open class Notification: View {
|
||||
if !UIDevice.isIPad, newValue == .horizontal { return }
|
||||
_layout = newValue
|
||||
buttonsView.buttonPosition = _layout == .horizontal ? .center : .left
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
get { _layout }
|
||||
}
|
||||
@ -231,6 +231,8 @@ open class Notification: View {
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
|
||||
shouldUpdateView = false
|
||||
|
||||
titleLabel.reset()
|
||||
titleLabel.text = ""
|
||||
titleLabel.textStyle = UIDevice.isIPad ? .boldBodyLarge : .boldBodySmall
|
||||
@ -255,6 +257,9 @@ open class Notification: View {
|
||||
layout = .vertical
|
||||
hideCloseButton = false
|
||||
fullBleed = false
|
||||
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -86,47 +86,47 @@ open class RadioBox: Control, Changeable {
|
||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
open var text: String = "Default Text" { didSet { didChange() }}
|
||||
open var text: String = "Default Text" { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var textAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
|
||||
open var textAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var textAttributedText: NSAttributedString? {
|
||||
didSet {
|
||||
textLabel.useAttributedText = !(textAttributedText?.string.isEmpty ?? true)
|
||||
textLabel.attributedText = textAttributedText
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
open var subText: String? { didSet { didChange() }}
|
||||
open var subText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var subTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
|
||||
open var subTextAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var subTextAttributedText: NSAttributedString? {
|
||||
didSet {
|
||||
subTextLabel.useAttributedText = !(subTextAttributedText?.string.isEmpty ?? true)
|
||||
subTextLabel.attributedText = subTextAttributedText
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
open var subTextRight: String? { didSet { didChange() }}
|
||||
open var subTextRight: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var subTextRightAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
|
||||
open var subTextRightAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var subTextRightAttributedText: NSAttributedString? {
|
||||
didSet {
|
||||
subTextRightLabel.useAttributedText = !(subTextRightAttributedText?.string.isEmpty ?? true)
|
||||
subTextRightLabel.attributedText = subTextRightAttributedText
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
open var strikethrough: Bool = false { didSet { didChange() }}
|
||||
open var strikethrough: Bool = false { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var inputId: String? { didSet { didChange() }}
|
||||
open var inputId: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var value: AnyHashable? { didSet { didChange() }}
|
||||
open var value: AnyHashable? { didSet { setNeedsUpdate() }}
|
||||
|
||||
//functions
|
||||
//--------------------------------------------------
|
||||
@ -204,6 +204,7 @@ open class RadioBox: Control, Changeable {
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
shouldUpdateView = false
|
||||
textLabel.reset()
|
||||
subTextLabel.reset()
|
||||
subTextRightLabel.reset()
|
||||
@ -227,7 +228,8 @@ open class RadioBox: Control, Changeable {
|
||||
|
||||
isSelected = false
|
||||
|
||||
updateSelector()
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
/// This will radioBox the state of the Selector and execute the actionBlock if provided.
|
||||
|
||||
@ -92,31 +92,31 @@ open class RadioButton: Control, Errorable, Changeable {
|
||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
open var labelText: String? { didSet { didChange() }}
|
||||
open var labelText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var labelTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
|
||||
open var labelTextAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var labelAttributedText: NSAttributedString? {
|
||||
didSet {
|
||||
label.useAttributedText = !(labelAttributedText?.string.isEmpty ?? true)
|
||||
label.attributedText = labelAttributedText
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
open var childText: String? { didSet { didChange() }}
|
||||
open var childText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var childTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
|
||||
open var childTextAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var childAttributedText: NSAttributedString? {
|
||||
didSet {
|
||||
childLabel.useAttributedText = !(childAttributedText?.string.isEmpty ?? true)
|
||||
childLabel.attributedText = childAttributedText
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
open var showError: Bool = false { didSet { didChange() }}
|
||||
open var showError: Bool = false { didSet { setNeedsUpdate() }}
|
||||
|
||||
open override var state: UIControl.State {
|
||||
get {
|
||||
@ -128,11 +128,11 @@ open class RadioButton: Control, Errorable, Changeable {
|
||||
}
|
||||
}
|
||||
|
||||
open var errorText: String? { didSet { didChange() }}
|
||||
open var errorText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var inputId: String? { didSet { didChange() }}
|
||||
open var inputId: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var value: AnyHashable? { didSet { didChange() }}
|
||||
open var value: AnyHashable? { didSet { setNeedsUpdate() }}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
@ -240,6 +240,7 @@ open class RadioButton: Control, Errorable, Changeable {
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
shouldUpdateView = false
|
||||
label.reset()
|
||||
childLabel.reset()
|
||||
errorLabel.reset()
|
||||
@ -261,7 +262,9 @@ open class RadioButton: Control, Errorable, Changeable {
|
||||
|
||||
isSelected = false
|
||||
|
||||
updateSelector()
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
|
||||
}
|
||||
|
||||
/// This will checkbox the state of the Selector and execute the actionBlock if provided.
|
||||
|
||||
@ -41,19 +41,19 @@ open class RadioSwatch: Control {
|
||||
$0.contentMode = .scaleAspectFit
|
||||
}
|
||||
|
||||
open var fillImage: UIImage? { didSet { didChange() }}
|
||||
open var fillImage: UIImage? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var text: String = "" { didSet { didChange() }}
|
||||
open var text: String = "" { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var primaryColor: UIColor? { didSet { didChange() }}
|
||||
open var primaryColor: UIColor? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var secondaryColor: UIColor? { didSet { didChange() }}
|
||||
open var secondaryColor: UIColor? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var strikethrough: Bool = false { didSet { didChange() }}
|
||||
open var strikethrough: Bool = false { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var inputId: String? { didSet { didChange() }}
|
||||
open var inputId: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var value: AnyHashable? { didSet { didChange() }}
|
||||
open var value: AnyHashable? { didSet { setNeedsUpdate() }}
|
||||
|
||||
//functions
|
||||
//--------------------------------------------------
|
||||
@ -91,7 +91,7 @@ open class RadioSwatch: Control {
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
|
||||
shouldUpdateView = false
|
||||
fillImage = nil
|
||||
text = ""
|
||||
primaryColor = nil
|
||||
@ -99,7 +99,8 @@ open class RadioSwatch: Control {
|
||||
strikethrough = false
|
||||
inputId = nil
|
||||
value = nil
|
||||
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
setNeedsDisplay()
|
||||
}
|
||||
|
||||
|
||||
@ -183,7 +183,7 @@ open class RadioSwatchGroup: SelectorGroupSelectedHandlerBase<RadioSwatch>, UICo
|
||||
selectedHandler?.toggle()
|
||||
selector.toggle()
|
||||
label.text = selector.text
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
valueChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,11 +106,10 @@ open class EntryField: Control, Changeable {
|
||||
}
|
||||
}
|
||||
|
||||
open var titleLabel = TrailingTooltipLabel().with {
|
||||
open var titleLabel = Label().with {
|
||||
$0.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
$0.labelTextPosition = .left
|
||||
$0.labelTextStyle = .bodySmall
|
||||
$0.tooltipYOffset = -2
|
||||
$0.textPosition = .left
|
||||
$0.textStyle = .bodySmall
|
||||
}
|
||||
|
||||
open var errorLabel = Label().with {
|
||||
@ -130,11 +129,11 @@ open class EntryField: Control, Changeable {
|
||||
$0.size = .small
|
||||
}
|
||||
|
||||
open var labelText: String? { didSet { didChange() }}
|
||||
open var labelText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var helperText: String? { didSet { didChange() }}
|
||||
open var helperText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var showError: Bool = false { didSet { didChange() }}
|
||||
open var showError: Bool = false { didSet { setNeedsUpdate() }}
|
||||
|
||||
open override var state: UIControl.State {
|
||||
get {
|
||||
@ -146,27 +145,27 @@ open class EntryField: Control, Changeable {
|
||||
}
|
||||
}
|
||||
|
||||
open var errorText: String? { didSet { didChange() }}
|
||||
open var errorText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var tooltipTitle: String? { didSet { didChange() }}
|
||||
open var tooltipTitle: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var tooltipContent: String? { didSet { didChange() }}
|
||||
open var tooltipContent: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var transparentBackground: Bool = false { didSet { didChange() }}
|
||||
open var transparentBackground: Bool = false { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var width: CGFloat? { didSet { didChange() }}
|
||||
open var width: CGFloat? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var maxLength: Int? { didSet { didChange() }}
|
||||
open var maxLength: Int? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var inputId: String? { didSet { didChange() }}
|
||||
open var inputId: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var value: AnyHashable? { didSet { didChange() }}
|
||||
open var value: AnyHashable? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var defaultValue: AnyHashable? { didSet { didChange() }}
|
||||
open var defaultValue: AnyHashable? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var required: Bool = false { didSet { didChange() }}
|
||||
open var required: Bool = false { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var readOnly: Bool = false { didSet { didChange() }}
|
||||
open var readOnly: Bool = false { didSet { setNeedsUpdate() }}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
@ -234,8 +233,8 @@ open class EntryField: Control, Changeable {
|
||||
errorLabel.reset()
|
||||
helperLabel.reset()
|
||||
|
||||
titleLabel.labelTextPosition = .left
|
||||
titleLabel.labelTextStyle = .bodySmall
|
||||
titleLabel.textPosition = .left
|
||||
titleLabel.textStyle = .bodySmall
|
||||
errorLabel.textPosition = .left
|
||||
errorLabel.textStyle = .bodySmall
|
||||
helperLabel.textPosition = .left
|
||||
@ -283,19 +282,23 @@ open class EntryField: Control, Changeable {
|
||||
|
||||
//dealing with the "Optional" addition to the text
|
||||
if let oldText = updatedLabelText, !required, !oldText.hasSuffix("Optional") {
|
||||
let optionColorAttr = ColorLabelAttribute(location: oldText.count + 2,
|
||||
length: 8,
|
||||
color: .red)
|
||||
|
||||
updatedLabelText = "\(oldText) Optional"
|
||||
attributes.append(optionColorAttr)
|
||||
}
|
||||
if !disabled {
|
||||
let optionColorAttr = ColorLabelAttribute(location: oldText.count + 2,
|
||||
length: 8,
|
||||
color: VDSColor.elementsSecondaryOnlight)
|
||||
|
||||
attributes.append(optionColorAttr)
|
||||
}
|
||||
updatedLabelText = "\(oldText) Optional"
|
||||
}
|
||||
|
||||
if let tooltipTitle, let tooltipContent {
|
||||
attributes.append(TooltipLabelAttribute(surface: surface, title: tooltipTitle, content: tooltipContent))
|
||||
}
|
||||
|
||||
//set the titleLabel
|
||||
titleLabel.labelText = updatedLabelText
|
||||
titleLabel.labelAttributes = attributes
|
||||
titleLabel.tooltipTitle = tooltipTitle ?? ""
|
||||
titleLabel.tooltipContent = tooltipContent ?? ""
|
||||
titleLabel.text = updatedLabelText
|
||||
titleLabel.attributes = attributes
|
||||
titleLabel.surface = surface
|
||||
titleLabel.disabled = disabled
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ open class InputField: EntryField, UITextFieldDelegate {
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
open var type: FieldType = .text { didSet { didChange() }}
|
||||
open var type: FieldType = .text { didSet { setNeedsUpdate() }}
|
||||
|
||||
var _showError: Bool = false
|
||||
open override var showError: Bool {
|
||||
@ -59,7 +59,7 @@ open class InputField: EntryField, UITextFieldDelegate {
|
||||
set {
|
||||
if !showSuccess && _showError != newValue {
|
||||
_showError = newValue
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,7 @@ open class InputField: EntryField, UITextFieldDelegate {
|
||||
set {
|
||||
if !showError && _showSuccess != newValue {
|
||||
_showSuccess = newValue
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,9 +85,9 @@ open class InputField: EntryField, UITextFieldDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
open var successText: String? { didSet { didChange() }}
|
||||
open var successText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var helperTextPlacement: HelperTextPlacement = .bottom { didSet { didChange() }}
|
||||
open var helperTextPlacement: HelperTextPlacement = .bottom { didSet { setNeedsUpdate() }}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Properties
|
||||
|
||||
@ -77,7 +77,7 @@ open class TileContainer: Control {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
public var backgroundImage: UIImage? { didSet{ didChange() } }
|
||||
public var backgroundImage: UIImage? { didSet{ setNeedsUpdate() } }
|
||||
|
||||
public var containerView = View().with {
|
||||
$0.isUserInteractionEnabled = false
|
||||
@ -87,13 +87,13 @@ open class TileContainer: Control {
|
||||
$0.isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
public var color: BackgroundColor = .white { didSet{ didChange() } }
|
||||
public var color: BackgroundColor = .white { didSet{ setNeedsUpdate() } }
|
||||
|
||||
public var padding: Padding = .padding4X { didSet{ didChange() } }
|
||||
public var padding: Padding = .padding4X { didSet{ setNeedsUpdate() } }
|
||||
|
||||
public var aspectRatio: AspectRatio = .ratio1x1 { didSet{ didChange() } }
|
||||
public var aspectRatio: AspectRatio = .ratio1x1 { didSet{ setNeedsUpdate() } }
|
||||
|
||||
public var imageFallbackColor: Surface = .light { didSet{ didChange() } }
|
||||
public var imageFallbackColor: Surface = .light { didSet{ setNeedsUpdate() } }
|
||||
|
||||
private var _width: CGFloat?
|
||||
public var width: CGFloat? {
|
||||
@ -104,7 +104,7 @@ open class TileContainer: Control {
|
||||
} else {
|
||||
_width = nil
|
||||
}
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,13 +117,13 @@ open class TileContainer: Control {
|
||||
} else {
|
||||
_height = nil
|
||||
}
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
public var showBorder: Bool = false { didSet{ didChange() } }
|
||||
public var showBorder: Bool = false { didSet{ setNeedsUpdate() } }
|
||||
|
||||
public var showDropShadows: Bool = false { didSet{ didChange() } }
|
||||
public var showDropShadows: Bool = false { didSet{ setNeedsUpdate() } }
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Properties
|
||||
@ -191,7 +191,17 @@ open class TileContainer: Control {
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
|
||||
shouldUpdateView = false
|
||||
color = .white
|
||||
padding = .padding4X
|
||||
aspectRatio = .ratio1x1
|
||||
imageFallbackColor = .light
|
||||
width = nil
|
||||
height = nil
|
||||
showBorder = false
|
||||
showDropShadows = false
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -153,7 +153,7 @@ open class Tilelet: TileContainer {
|
||||
} else {
|
||||
_textWidth = nil
|
||||
}
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
}
|
||||
@ -170,16 +170,16 @@ open class Tilelet: TileContainer {
|
||||
} else {
|
||||
_textPercentage = nil
|
||||
}
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
open var textPostion: TextPosition = .top { didSet { didChange() }}
|
||||
open var textPostion: TextPosition = .top { didSet { setNeedsUpdate() }}
|
||||
|
||||
//models
|
||||
public var badgeModel: BadgeModel? { didSet { didChange() }}
|
||||
public var titleModel: TitleModel? { didSet { didChange() }}
|
||||
public var subTitleModel: SubTitleModel? { didSet { didChange() }}
|
||||
public var badgeModel: BadgeModel? { didSet { setNeedsUpdate() }}
|
||||
public var titleModel: TitleModel? { didSet { setNeedsUpdate() }}
|
||||
public var subTitleModel: SubTitleModel? { didSet { setNeedsUpdate() }}
|
||||
|
||||
//only 1 Icon can be active
|
||||
private var _descriptiveIconModel: DescriptiveIcon?
|
||||
@ -188,7 +188,7 @@ open class Tilelet: TileContainer {
|
||||
set {
|
||||
_descriptiveIconModel = newValue;
|
||||
_directionalIconModel = nil
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ open class Tilelet: TileContainer {
|
||||
set {
|
||||
_directionalIconModel = newValue;
|
||||
_descriptiveIconModel = nil
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
//icons
|
||||
@ -256,15 +256,17 @@ open class Tilelet: TileContainer {
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
shouldUpdateView = false
|
||||
aspectRatio = .none
|
||||
color = .black
|
||||
|
||||
//models
|
||||
badgeModel = nil
|
||||
titleModel = nil
|
||||
subTitleModel = nil
|
||||
descriptiveIconModel = nil
|
||||
directionalIconModel = nil
|
||||
directionalIconModel = nil
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -173,28 +173,32 @@ open class TitleLockup: View {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
open var textPosition: TextPosition = .left { didSet { didChange() }}
|
||||
open var textPosition: TextPosition = .left { didSet { setNeedsUpdate() }}
|
||||
|
||||
//style
|
||||
open var otherTextStyle: OtherTextStyle = UIDevice.isIPad ? .bodyLarge : .bodyMedium { didSet { didChange() }}
|
||||
open var otherTextStyle: OtherTextStyle = UIDevice.isIPad ? .bodyLarge : .bodyMedium {
|
||||
didSet {
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
//first row
|
||||
open var eyebrowLabel = Label().with {
|
||||
$0.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
}
|
||||
open var eyebrowModel: EyebrowModel? { didSet { didChange() }}
|
||||
open var eyebrowModel: EyebrowModel? { didSet { setNeedsUpdate() }}
|
||||
|
||||
//second row
|
||||
open var titleLabel = Label().with {
|
||||
$0.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
}
|
||||
open var titleModel: TitleModel? { didSet { didChange() }}
|
||||
open var titleModel: TitleModel? { didSet { setNeedsUpdate() }}
|
||||
|
||||
//third row
|
||||
open var subTitleLabel = Label().with {
|
||||
$0.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
}
|
||||
open var subTitleModel: SubTitleModel? { didSet { didChange() }}
|
||||
open var subTitleModel: SubTitleModel? { didSet { setNeedsUpdate() }}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
@ -218,17 +222,14 @@ open class TitleLockup: View {
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
titleLabel.reset()
|
||||
eyebrowLabel.reset()
|
||||
subTitleLabel.reset()
|
||||
|
||||
shouldUpdateView = false
|
||||
textPosition = .left
|
||||
|
||||
eyebrowModel = nil
|
||||
titleModel = nil
|
||||
subTitleModel = nil
|
||||
otherTextStyle = .bodyLarge
|
||||
|
||||
otherTextStyle = UIDevice.isIPad ? .bodyLarge : .bodyMedium
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -241,7 +242,7 @@ open class TitleLockup: View {
|
||||
var eyebrowTextIsEmpty = true
|
||||
var titleTextIsEmpty = true
|
||||
var subTitleTextIsEmpty = true
|
||||
|
||||
|
||||
if let eyebrowModel, !eyebrowModel.text.isEmpty {
|
||||
eyebrowTextIsEmpty = false
|
||||
eyebrowLabel.textPosition = allLabelsTextPosition
|
||||
|
||||
@ -125,27 +125,27 @@ open class Toggle: Control, Changeable {
|
||||
if isSelected != newValue {
|
||||
isSelected = newValue
|
||||
}
|
||||
didChange()
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
open var isAnimated: Bool = true { didSet { didChange() }}
|
||||
open var isAnimated: Bool = true { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var showText: Bool = false { didSet { didChange() }}
|
||||
open var showText: Bool = false { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var onText: String = "On" { didSet { didChange() }}
|
||||
open var onText: String = "On" { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var offText: String = "Off" { didSet { didChange() }}
|
||||
open var offText: String = "Off" { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var textSize: TextSize = .small { didSet { didChange() }}
|
||||
open var textSize: TextSize = .small { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var textWeight: TextWeight = .regular { didSet { didChange() }}
|
||||
open var textWeight: TextWeight = .regular { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var textPosition: TextPosition = .left { didSet { didChange() }}
|
||||
open var textPosition: TextPosition = .left { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var inputId: String? { didSet { didChange() }}
|
||||
open var inputId: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var value: AnyHashable? { didSet { didChange() }}
|
||||
open var value: AnyHashable? { didSet { setNeedsUpdate() }}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
@ -272,9 +272,9 @@ open class Toggle: Control, Changeable {
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
shouldUpdateView = false
|
||||
label.reset()
|
||||
isOn = false
|
||||
|
||||
isAnimated = true
|
||||
showText = false
|
||||
onText = "On"
|
||||
@ -284,9 +284,10 @@ open class Toggle: Control, Changeable {
|
||||
textPosition = .left
|
||||
inputId = nil
|
||||
value = nil
|
||||
|
||||
toggleView.backgroundColor = toggleColorConfiguration.getColor(self)
|
||||
knobView.backgroundColor = knobColorConfiguration.getColor(self)
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
/// This will toggle the state of the Toggle and execute the actionBlock if provided.
|
||||
|
||||
@ -44,15 +44,15 @@ open class Tooltip: Control, TooltipLaunchable {
|
||||
$0.clipsToBounds = true
|
||||
}
|
||||
|
||||
open var closeButtonText: String = "Close" { didSet { didChange() }}
|
||||
open var closeButtonText: String = "Close" { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var fillColor: FillColor = .primary { didSet { didChange() }}
|
||||
open var fillColor: FillColor = .primary { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var size: Size = .medium { didSet { didChange() }}
|
||||
open var size: Size = .medium { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var title: String = "" { didSet { didChange() }}
|
||||
open var title: String = "" { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var content: String = "" { didSet { didChange() }}
|
||||
open var content: String = "" { didSet { setNeedsUpdate() }}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Configuration
|
||||
@ -138,12 +138,15 @@ open class Tooltip: Control, TooltipLaunchable {
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
shouldUpdateView = false
|
||||
size = .medium
|
||||
title = ""
|
||||
content = ""
|
||||
fillColor = .primary
|
||||
closeButtonText = "Close"
|
||||
imageView.image = nil
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
open override func updateView() {
|
||||
|
||||
@ -22,25 +22,24 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
|
||||
//--------------------------------------------------
|
||||
open var label = Label()
|
||||
|
||||
open var labelText: String? { didSet { didChange() }}
|
||||
open var labelText: String? { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var labelAttributes: [any LabelAttributeModel]? { didSet { didChange() } }
|
||||
open var labelAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var labelTextStyle: TextStyle = .defaultStyle { didSet { didChange() } }
|
||||
open var labelTextStyle: TextStyle = .defaultStyle { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var labelTextPosition: TextPosition = .left { didSet { didChange() } }
|
||||
open var labelTextPosition: TextPosition = .left { didSet { setNeedsUpdate() } }
|
||||
|
||||
public lazy var textColorConfiguration: AnyColorable = {
|
||||
label.textColorConfiguration
|
||||
}() { didSet { didChange() }}
|
||||
}() { didSet { setNeedsUpdate() }}
|
||||
|
||||
open var tooltipCloseButtonText: String = "Close" { didSet { didChange() } }
|
||||
open var tooltipCloseButtonText: String = "Close" { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var tooltipTitle: String = "" { didSet { didChange() } }
|
||||
open var tooltipTitle: String = "" { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var tooltipContent: String = "" { didSet { didChange() } }
|
||||
open var tooltipContent: String = "" { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var tooltipYOffset: CGFloat = 0 { didSet { didChange() } }
|
||||
//--------------------------------------------------
|
||||
// MARK: - Overrides
|
||||
//--------------------------------------------------
|
||||
@ -75,6 +74,20 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
|
||||
label.addTooltip(model: .init(surface: surface, closeButtonText: tooltipCloseButtonText, title: tooltipTitle, content: tooltipContent))
|
||||
}
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
shouldUpdateView = false
|
||||
labelText = nil
|
||||
labelAttributes = nil
|
||||
labelTextStyle = .defaultStyle
|
||||
labelTextPosition = .left
|
||||
tooltipCloseButtonText = "Close"
|
||||
tooltipTitle = ""
|
||||
tooltipContent = ""
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -10,38 +10,21 @@ import Combine
|
||||
import UIKit
|
||||
|
||||
public protocol Handlerable: AnyObject, Initable, Disabling, Surfaceable {
|
||||
var subject: PassthroughSubject<Void, Never> { get set }
|
||||
var subscribers: Set<AnyCancellable> { get set }
|
||||
var shouldUpdateView: Bool { get set }
|
||||
func updateView()
|
||||
}
|
||||
|
||||
extension Handlerable {
|
||||
|
||||
public func setupDidChangeEvent(_ debounce: Bool = false) {
|
||||
handlerPublisher(debounce)
|
||||
.sink { [weak self] _ in
|
||||
self?.updateView()
|
||||
}.store(in: &subscribers)
|
||||
}
|
||||
|
||||
public func handlerPublisher(_ debounce: Bool = false) -> AnyPublisher<Void, Never> {
|
||||
if debounce {
|
||||
return subject
|
||||
.debounce(for: .seconds(Constants.StateDebounce), scheduler: RunLoop.main)
|
||||
.eraseToAnyPublisher()
|
||||
} else {
|
||||
return subject
|
||||
.eraseToAnyPublisher()
|
||||
public func setNeedsUpdate() {
|
||||
if shouldUpdateView {
|
||||
shouldUpdateView = false
|
||||
updateView()
|
||||
shouldUpdateView = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Handlerable where Self: UIView {
|
||||
public func didChange() {
|
||||
subject.send()
|
||||
}
|
||||
}
|
||||
|
||||
extension Handlerable where Self: UIControl {
|
||||
public func addEvent(event: UIControl.Event, block: @escaping (Self)->()) {
|
||||
publisher(for: event)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user