Compare commits
14 Commits
develop
...
feature/su
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0090deac9 | ||
|
|
4fd167cfa3 | ||
|
|
df1e8ee2df | ||
|
|
ce54965edc | ||
|
|
0be0d71f7b | ||
|
|
c2998ee0bf | ||
|
|
ac1e6f692d | ||
|
|
c7e47707c2 | ||
|
|
3e8c6a12e4 | ||
|
|
d159075f83 | ||
|
|
a8e1cf9b48 | ||
|
|
76c3205921 | ||
|
|
abc7f409e7 | ||
|
|
1934da2543 |
@ -16,6 +16,8 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Combine Properties
|
// MARK: - Combine Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
public var subject = PassthroughSubject<Void, Never>()
|
||||||
|
public var updateStrategy: HandlerableUpdateStrategy = .immediate
|
||||||
|
|
||||||
/// Set of Subscribers for any Publishers for this Control
|
/// Set of Subscribers for any Publishers for this Control
|
||||||
public var subscribers = Set<AnyCancellable>()
|
public var subscribers = Set<AnyCancellable>()
|
||||||
@ -33,10 +35,7 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
|
|||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private var initialSetupPerformed = false
|
private var initialSetupPerformed = false
|
||||||
|
|
||||||
/// Key of whether or not updateView() is called in setNeedsUpdate()
|
|
||||||
open var shouldUpdateView: Bool = true
|
|
||||||
|
|
||||||
/// Dictionary for keeping information for this Control use only Primitives
|
/// Dictionary for keeping information for this Control use only Primitives
|
||||||
open var userInfo = [String: Primitive]()
|
open var userInfo = [String: Primitive]()
|
||||||
|
|
||||||
@ -109,7 +108,8 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
|
|||||||
if !initialSetupPerformed {
|
if !initialSetupPerformed {
|
||||||
initialSetupPerformed = true
|
initialSetupPerformed = true
|
||||||
setup()
|
setup()
|
||||||
setNeedsUpdate()
|
setupNeedsUpdateEvent()
|
||||||
|
updateView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +125,14 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Overrides
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
open override func didMoveToWindow() {
|
||||||
|
super.didMoveToWindow()
|
||||||
|
// Keep the strategy if it's 'alwaysImmediate'
|
||||||
|
guard updateStrategy != .alwaysImmediate else { return }
|
||||||
|
|
||||||
|
// Update the strategy based on whether the view is in a window
|
||||||
|
updateStrategy = window != nil ? .delayed : .immediate
|
||||||
|
}
|
||||||
|
|
||||||
/// Update this view based off of property changes
|
/// Update this view based off of property changes
|
||||||
open func updateView() {
|
open func updateView() {
|
||||||
|
|||||||
@ -229,7 +229,6 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
label.reset()
|
label.reset()
|
||||||
childLabel.reset()
|
childLabel.reset()
|
||||||
errorLabel.reset()
|
errorLabel.reset()
|
||||||
@ -250,7 +249,6 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
|
|||||||
value = nil
|
value = nil
|
||||||
isSelected = false
|
isSelected = false
|
||||||
|
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,16 +17,16 @@ open class View: UIView, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Combine Properties
|
// MARK: - Combine Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
public var subject = PassthroughSubject<Void, Never>()
|
||||||
|
public var updateStrategy: HandlerableUpdateStrategy = .immediate
|
||||||
|
|
||||||
public var subscribers = Set<AnyCancellable>()
|
public var subscribers = Set<AnyCancellable>()
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private var initialSetupPerformed = false
|
private var initialSetupPerformed = false
|
||||||
|
|
||||||
/// Key of whether or not updateView() is called in setNeedsUpdate()
|
|
||||||
open var shouldUpdateView: Bool = true
|
|
||||||
|
|
||||||
/// Dictionary for keeping information for this Control use only Primitives
|
/// Dictionary for keeping information for this Control use only Primitives
|
||||||
open var userInfo = [String: Primitive]()
|
open var userInfo = [String: Primitive]()
|
||||||
|
|
||||||
@ -72,13 +72,22 @@ open class View: UIView, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
|||||||
if !initialSetupPerformed {
|
if !initialSetupPerformed {
|
||||||
initialSetupPerformed = true
|
initialSetupPerformed = true
|
||||||
setup()
|
setup()
|
||||||
setNeedsUpdate()
|
setupNeedsUpdateEvent()
|
||||||
|
updateView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Overrides
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
open override func didMoveToWindow() {
|
||||||
|
super.didMoveToWindow()
|
||||||
|
// Keep the strategy if it's 'alwaysImmediate'
|
||||||
|
guard updateStrategy != .alwaysImmediate else { return }
|
||||||
|
|
||||||
|
// Update the strategy based on whether the view is in a window
|
||||||
|
updateStrategy = window != nil ? .delayed : .immediate
|
||||||
|
}
|
||||||
|
|
||||||
/// Update this view based off of property changes
|
/// Update this view based off of property changes
|
||||||
open func updateView() {
|
open func updateView() {
|
||||||
|
|||||||
@ -78,7 +78,6 @@ open class Badge: View {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
label.reset()
|
label.reset()
|
||||||
label.lineBreakMode = .byTruncatingTail
|
label.lineBreakMode = .byTruncatingTail
|
||||||
label.textPosition = .left
|
label.textPosition = .left
|
||||||
@ -87,7 +86,6 @@ open class Badge: View {
|
|||||||
text = ""
|
text = ""
|
||||||
maxWidth = nil
|
maxWidth = nil
|
||||||
numberOfLines = 1
|
numberOfLines = 1
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -281,13 +281,11 @@ open class BadgeIndicator: View {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
label.reset()
|
label.reset()
|
||||||
label.lineBreakMode = .byTruncatingTail
|
label.lineBreakMode = .byTruncatingTail
|
||||||
label.textPosition = .center
|
label.textPosition = .center
|
||||||
fillColor = .red
|
fillColor = .red
|
||||||
number = nil
|
number = nil
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -133,11 +133,9 @@ open class Button: ButtonBase, Useable {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
use = .primary
|
use = .primary
|
||||||
width = nil
|
width = nil
|
||||||
size = .large
|
size = .large
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,8 @@ open class ButtonBase: UIButton, Buttonable, Handlerable, ViewProtocol, Resettab
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Combine Properties
|
// MARK: - Combine Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
public var subject = PassthroughSubject<Void, Never>()
|
||||||
|
public var updateStrategy: HandlerableUpdateStrategy = .immediate
|
||||||
public var subscribers = Set<AnyCancellable>()
|
public var subscribers = Set<AnyCancellable>()
|
||||||
public var onClickSubscriber: AnyCancellable? {
|
public var onClickSubscriber: AnyCancellable? {
|
||||||
willSet {
|
willSet {
|
||||||
@ -44,9 +46,7 @@ open class ButtonBase: UIButton, Buttonable, Handlerable, ViewProtocol, Resettab
|
|||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
open var shouldUpdateView: Bool = true
|
|
||||||
|
|
||||||
open var availableSizes: [ButtonSize] { [] }
|
open var availableSizes: [ButtonSize] { [] }
|
||||||
|
|
||||||
open var text: String? { didSet { setNeedsUpdate() } }
|
open var text: String? { didSet { setNeedsUpdate() } }
|
||||||
@ -123,7 +123,8 @@ open class ButtonBase: UIButton, Buttonable, Handlerable, ViewProtocol, Resettab
|
|||||||
translatesAutoresizingMaskIntoConstraints = false
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
accessibilityCustomActions = []
|
accessibilityCustomActions = []
|
||||||
setup()
|
setup()
|
||||||
setNeedsUpdate()
|
setupNeedsUpdateEvent()
|
||||||
|
updateView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,18 +138,25 @@ open class ButtonBase: UIButton, Buttonable, Handlerable, ViewProtocol, Resettab
|
|||||||
|
|
||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open func reset() {
|
open func reset() {
|
||||||
shouldUpdateView = false
|
|
||||||
surface = .light
|
surface = .light
|
||||||
disabled = false
|
disabled = false
|
||||||
text = nil
|
text = nil
|
||||||
accessibilityCustomActions = []
|
accessibilityCustomActions = []
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Overrides
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
open override func didMoveToWindow() {
|
||||||
|
super.didMoveToWindow()
|
||||||
|
// Keep the strategy if it's 'alwaysImmediate'
|
||||||
|
guard updateStrategy != .alwaysImmediate else { return }
|
||||||
|
|
||||||
|
// Update the strategy based on whether the view is in a window
|
||||||
|
updateStrategy = window != nil ? .delayed : .immediate
|
||||||
|
}
|
||||||
|
|
||||||
override open var intrinsicContentSize: CGSize {
|
override open var intrinsicContentSize: CGSize {
|
||||||
let intrinsicContentSize = super.intrinsicContentSize
|
let intrinsicContentSize = super.intrinsicContentSize
|
||||||
let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
|
let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
|
||||||
|
|||||||
@ -90,13 +90,11 @@ open class TextLink: ButtonBase {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
text = nil
|
text = nil
|
||||||
size = .large
|
size = .large
|
||||||
accessibilityCustomActions = []
|
accessibilityCustomActions = []
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = true
|
||||||
accessibilityTraits = .link
|
accessibilityTraits = .link
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -256,7 +256,6 @@ open class ButtonIcon: Control {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
kind = .ghost
|
kind = .ghost
|
||||||
surfaceType = .colorFill
|
surfaceType = .colorFill
|
||||||
size = .large
|
size = .large
|
||||||
@ -264,7 +263,6 @@ open class ButtonIcon: Control {
|
|||||||
hideBorder = true
|
hideBorder = true
|
||||||
iconOffset = .init(x: 0, y: 0)
|
iconOffset = .init(x: 0, y: 0)
|
||||||
iconName = nil
|
iconName = nil
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,15 +16,15 @@ open class Label: UILabel, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Combine Properties
|
// MARK: - Combine Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
public var subject = PassthroughSubject<Void, Never>()
|
||||||
public var subscribers = Set<AnyCancellable>()
|
public var subscribers = Set<AnyCancellable>()
|
||||||
|
public var updateStrategy: HandlerableUpdateStrategy = .immediate
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private var initialSetupPerformed = false
|
private var initialSetupPerformed = false
|
||||||
|
|
||||||
open var shouldUpdateView: Bool = true
|
|
||||||
|
|
||||||
open var useAttributedText: Bool = false
|
open var useAttributedText: Bool = false
|
||||||
|
|
||||||
open var useScaledFont: Bool = false { didSet { setNeedsUpdate() }}
|
open var useScaledFont: Bool = false { didSet { setNeedsUpdate() }}
|
||||||
@ -105,7 +105,8 @@ open class Label: UILabel, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
|||||||
accessibilityCustomActions = []
|
accessibilityCustomActions = []
|
||||||
accessibilityTraits = .staticText
|
accessibilityTraits = .staticText
|
||||||
setup()
|
setup()
|
||||||
setNeedsUpdate()
|
setupNeedsUpdateEvent()
|
||||||
|
updateView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +114,6 @@ open class Label: UILabel, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
|||||||
|
|
||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open func reset() {
|
open func reset() {
|
||||||
shouldUpdateView = false
|
|
||||||
surface = .light
|
surface = .light
|
||||||
disabled = false
|
disabled = false
|
||||||
attributes = nil
|
attributes = nil
|
||||||
@ -123,7 +123,6 @@ open class Label: UILabel, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
|||||||
attributedText = nil
|
attributedText = nil
|
||||||
numberOfLines = 0
|
numberOfLines = 0
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +135,16 @@ open class Label: UILabel, Handlerable, ViewProtocol, Resettable, UserInfoable {
|
|||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Overrides
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
open override func didMoveToWindow() {
|
||||||
|
super.didMoveToWindow()
|
||||||
|
// Keep the strategy if it's 'alwaysImmediate'
|
||||||
|
guard updateStrategy != .alwaysImmediate else { return }
|
||||||
|
|
||||||
|
// Update the strategy based on whether the view is in a window
|
||||||
|
updateStrategy = window != nil ? .delayed : .immediate
|
||||||
|
}
|
||||||
|
|
||||||
open func updateView() {
|
open func updateView() {
|
||||||
if !useAttributedText {
|
if !useAttributedText {
|
||||||
if let text = text {
|
if let text = text {
|
||||||
|
|||||||
@ -231,9 +231,7 @@ open class Notification: View {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
|
|
||||||
shouldUpdateView = false
|
|
||||||
|
|
||||||
titleLabel.reset()
|
titleLabel.reset()
|
||||||
titleLabel.text = ""
|
titleLabel.text = ""
|
||||||
titleLabel.textStyle = UIDevice.isIPad ? .boldBodyLarge : .boldBodySmall
|
titleLabel.textStyle = UIDevice.isIPad ? .boldBodyLarge : .boldBodySmall
|
||||||
@ -259,7 +257,6 @@ open class Notification: View {
|
|||||||
hideCloseButton = false
|
hideCloseButton = false
|
||||||
fullBleed = false
|
fullBleed = false
|
||||||
|
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -203,7 +203,6 @@ open class RadioBoxItem: Control, Changeable {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
textLabel.reset()
|
textLabel.reset()
|
||||||
subTextLabel.reset()
|
subTextLabel.reset()
|
||||||
subTextRightLabel.reset()
|
subTextRightLabel.reset()
|
||||||
@ -227,7 +226,6 @@ open class RadioBoxItem: Control, Changeable {
|
|||||||
|
|
||||||
isSelected = false
|
isSelected = false
|
||||||
|
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -92,7 +92,6 @@ open class RadioSwatch: Control {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
fillImage = nil
|
fillImage = nil
|
||||||
text = ""
|
text = ""
|
||||||
primaryColor = nil
|
primaryColor = nil
|
||||||
@ -100,7 +99,6 @@ open class RadioSwatch: Control {
|
|||||||
strikethrough = false
|
strikethrough = false
|
||||||
inputId = nil
|
inputId = nil
|
||||||
value = nil
|
value = nil
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
setNeedsDisplay()
|
setNeedsDisplay()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -123,6 +123,9 @@ extension Tabs {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
|
updateStrategy = .alwaysImmediate
|
||||||
|
label.updateStrategy = .alwaysImmediate
|
||||||
|
|
||||||
addSubview(label)
|
addSubview(label)
|
||||||
accessibilityTraits = .button
|
accessibilityTraits = .button
|
||||||
|
|
||||||
@ -137,19 +140,7 @@ extension Tabs {
|
|||||||
|
|
||||||
labelLeadingConstraint = label.leadingAnchor.constraint(equalTo: leadingAnchor)
|
labelLeadingConstraint = label.leadingAnchor.constraint(equalTo: leadingAnchor)
|
||||||
labelLeadingConstraint?.isActive = true
|
labelLeadingConstraint?.isActive = true
|
||||||
|
|
||||||
let layoutGuide = UILayoutGuide()
|
|
||||||
addLayoutGuide(layoutGuide)
|
|
||||||
|
|
||||||
labelWidthConstraint = layoutGuide.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidth)
|
|
||||||
labelWidthConstraint?.isActive = true
|
|
||||||
|
|
||||||
//activate the constraints
|
|
||||||
NSLayoutConstraint.activate([layoutGuide.topAnchor.constraint(equalTo: topAnchor),
|
|
||||||
layoutGuide.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
||||||
layoutGuide.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
||||||
layoutGuide.trailingAnchor.constraint(equalTo: trailingAnchor)])
|
|
||||||
|
|
||||||
publisher(for: UITapGestureRecognizer())
|
publisher(for: UITapGestureRecognizer())
|
||||||
.sink { [weak self] _ in
|
.sink { [weak self] _ in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
|
|||||||
@ -164,6 +164,7 @@ open class Tabs: View {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
|
updateStrategy = .alwaysImmediate
|
||||||
scrollView = UIScrollView()
|
scrollView = UIScrollView()
|
||||||
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
scrollView.showsHorizontalScrollIndicator = false
|
scrollView.showsHorizontalScrollIndicator = false
|
||||||
|
|||||||
@ -192,7 +192,6 @@ open class TileContainer: Control {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
color = .white
|
color = .white
|
||||||
padding = .padding4X
|
padding = .padding4X
|
||||||
aspectRatio = .ratio1x1
|
aspectRatio = .ratio1x1
|
||||||
@ -201,7 +200,6 @@ open class TileContainer: Control {
|
|||||||
height = nil
|
height = nil
|
||||||
showBorder = false
|
showBorder = false
|
||||||
showDropShadows = false
|
showDropShadows = false
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -242,7 +242,6 @@ open class Tilelet: TileContainer {
|
|||||||
|
|
||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
shouldUpdateView = false
|
|
||||||
aspectRatio = .none
|
aspectRatio = .none
|
||||||
color = .black
|
color = .black
|
||||||
//models
|
//models
|
||||||
@ -251,7 +250,6 @@ open class Tilelet: TileContainer {
|
|||||||
subTitleModel = nil
|
subTitleModel = nil
|
||||||
descriptiveIconModel = nil
|
descriptiveIconModel = nil
|
||||||
directionalIconModel = nil
|
directionalIconModel = nil
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -199,12 +199,10 @@ open class TitleLockup: View {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
textPosition = .left
|
textPosition = .left
|
||||||
eyebrowModel = nil
|
eyebrowModel = nil
|
||||||
titleModel = nil
|
titleModel = nil
|
||||||
subTitleModel = nil
|
subTitleModel = nil
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -175,7 +175,6 @@ open class Toggle: Control, Changeable {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
label.reset()
|
label.reset()
|
||||||
isOn = false
|
isOn = false
|
||||||
isAnimated = true
|
isAnimated = true
|
||||||
@ -187,8 +186,6 @@ open class Toggle: Control, Changeable {
|
|||||||
textPosition = .left
|
textPosition = .left
|
||||||
inputId = nil
|
inputId = nil
|
||||||
value = nil
|
value = nil
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This will toggle the state of the Toggle
|
/// This will toggle the state of the Toggle
|
||||||
|
|||||||
@ -139,15 +139,12 @@ open class ToggleView: Control, Changeable {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
isOn = false
|
isOn = false
|
||||||
isAnimated = true
|
isAnimated = true
|
||||||
inputId = nil
|
inputId = nil
|
||||||
value = nil
|
value = nil
|
||||||
toggleView.backgroundColor = toggleColorConfiguration.getColor(self)
|
toggleView.backgroundColor = toggleColorConfiguration.getColor(self)
|
||||||
knobView.backgroundColor = knobColorConfiguration.getColor(self)
|
knobView.backgroundColor = knobColorConfiguration.getColor(self)
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This will toggle the state of the Toggle and execute the actionBlock if provided.
|
/// This will toggle the state of the Toggle and execute the actionBlock if provided.
|
||||||
|
|||||||
@ -142,14 +142,12 @@ open class Tooltip: Control, TooltipLaunchable {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
size = .medium
|
size = .medium
|
||||||
title = ""
|
title = ""
|
||||||
content = ""
|
content = ""
|
||||||
fillColor = .primary
|
fillColor = .primary
|
||||||
closeButtonText = "Close"
|
closeButtonText = "Close"
|
||||||
imageView.image = nil
|
imageView.image = nil
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -80,7 +80,6 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
|
|||||||
/// Resets back to this objects default settings.
|
/// Resets back to this objects default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
|
||||||
labelText = nil
|
labelText = nil
|
||||||
labelAttributes = nil
|
labelAttributes = nil
|
||||||
labelTextStyle = .defaultStyle
|
labelTextStyle = .defaultStyle
|
||||||
@ -88,7 +87,6 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
|
|||||||
tooltipCloseButtonText = "Close"
|
tooltipCloseButtonText = "Close"
|
||||||
tooltipTitle = ""
|
tooltipTitle = ""
|
||||||
tooltipContent = ""
|
tooltipContent = ""
|
||||||
shouldUpdateView = true
|
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,18 +9,43 @@ import Foundation
|
|||||||
import Combine
|
import Combine
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
public enum HandlerableUpdateStrategy {
|
||||||
|
case immediate
|
||||||
|
case delayed
|
||||||
|
case alwaysImmediate
|
||||||
|
case paused
|
||||||
|
}
|
||||||
|
|
||||||
public protocol Handlerable: AnyObject, Initable, Disabling, Surfaceable {
|
public protocol Handlerable: AnyObject, Initable, Disabling, Surfaceable {
|
||||||
|
var subject: PassthroughSubject<Void, Never> { get set }
|
||||||
var subscribers: Set<AnyCancellable> { get set }
|
var subscribers: Set<AnyCancellable> { get set }
|
||||||
var shouldUpdateView: Bool { get set }
|
var updateStrategy: HandlerableUpdateStrategy { get set }
|
||||||
func updateView()
|
func updateView()
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Handlerable {
|
extension Handlerable {
|
||||||
|
public func setupNeedsUpdateEvent() {
|
||||||
|
subject
|
||||||
|
.debounce(for: .milliseconds(50), scheduler: RunLoop.main)
|
||||||
|
.sink { [weak self] _ in
|
||||||
|
self?.updateView()
|
||||||
|
}.store(in: &subscribers)
|
||||||
|
}
|
||||||
|
|
||||||
public func setNeedsUpdate() {
|
public func setNeedsUpdate() {
|
||||||
if shouldUpdateView {
|
switch updateStrategy {
|
||||||
shouldUpdateView = false
|
case .delayed:
|
||||||
|
subject.send()
|
||||||
|
case .immediate, .alwaysImmediate:
|
||||||
updateView()
|
updateView()
|
||||||
shouldUpdateView = true
|
case .paused:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateIfNeeded<T: Equatable>(_ oldValue: T, _ newValue: T) {
|
||||||
|
if oldValue != newValue {
|
||||||
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,3 +58,15 @@ extension Handlerable where Self: UIControl {
|
|||||||
}).store(in: &subscribers)
|
}).store(in: &subscribers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Handlerable {
|
||||||
|
@discardableResult func pausedUpdate(_ closure: (_ instance: inout Self) -> Void) -> Self {
|
||||||
|
var copy = self
|
||||||
|
let oldStrategy = copy.updateStrategy
|
||||||
|
copy.updateStrategy = .paused
|
||||||
|
closure(©)
|
||||||
|
copy.updateStrategy = oldStrategy
|
||||||
|
copy.updateView()
|
||||||
|
return copy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user