From d336b8dfda6a0e40572816b37be3394d7b2c66df Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 15:11:12 -0500 Subject: [PATCH 1/4] trying to deal with rendering issues Signed-off-by: Matt Bruce --- VDS/BaseClasses/Selector/SelectorBase.swift | 4 +++- VDS/BaseClasses/Selector/SelectorGroupBase.swift | 3 ++- VDS/BaseClasses/Selector/SelectorItemBase.swift | 3 ++- VDS/Components/RadioBox/RadioBoxItem.swift | 3 ++- VDS/Protocols/ViewProtocol.swift | 11 +++++++++++ 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/VDS/BaseClasses/Selector/SelectorBase.swift b/VDS/BaseClasses/Selector/SelectorBase.swift index 6af003fd..2d12cf07 100644 --- a/VDS/BaseClasses/Selector/SelectorBase.swift +++ b/VDS/BaseClasses/Selector/SelectorBase.swift @@ -30,7 +30,9 @@ public protocol SelectorControlable: Control, Changeable { /// Base Class used to build out a Selector control. @objcMembers @objc(VDSSelectorBase) -open class SelectorBase: Control, SelectorControlable { +open class SelectorBase: Control, SelectorControlable, ParentViewProtocol { + public var children: [any ViewProtocol] { [selectorView] } + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- diff --git a/VDS/BaseClasses/Selector/SelectorGroupBase.swift b/VDS/BaseClasses/Selector/SelectorGroupBase.swift index e04b5e5a..ebb0512b 100644 --- a/VDS/BaseClasses/Selector/SelectorGroupBase.swift +++ b/VDS/BaseClasses/Selector/SelectorGroupBase.swift @@ -39,7 +39,8 @@ extension SelectorGroupSingleSelect { } /// Base Class used for any Grouped Form Control of a Selector Type. -open class SelectorGroupBase: Control, SelectorGroup, Changeable { +open class SelectorGroupBase: Control, SelectorGroup, Changeable, ParentViewProtocol { + public var children: [any ViewProtocol] { items } //-------------------------------------------------- // MARK: - Private Properties diff --git a/VDS/BaseClasses/Selector/SelectorItemBase.swift b/VDS/BaseClasses/Selector/SelectorItemBase.swift index ea037771..d2ccc293 100644 --- a/VDS/BaseClasses/Selector/SelectorItemBase.swift +++ b/VDS/BaseClasses/Selector/SelectorItemBase.swift @@ -11,7 +11,8 @@ import Combine import VDSCoreTokens /// Base Class used to build out a SelectorControlable control. -open class SelectorItemBase: Control, Errorable, Changeable, Groupable { +open class SelectorItemBase: Control, Errorable, Changeable, Groupable, ParentViewProtocol { + public var children: [any ViewProtocol] { [label, childLabel, errorLabel, selectorView] } //-------------------------------------------------- // MARK: - Initializers diff --git a/VDS/Components/RadioBox/RadioBoxItem.swift b/VDS/Components/RadioBox/RadioBoxItem.swift index a5ca1d8b..b8530363 100644 --- a/VDS/Components/RadioBox/RadioBoxItem.swift +++ b/VDS/Components/RadioBox/RadioBoxItem.swift @@ -14,7 +14,8 @@ import VDSCoreTokens /// that are used within a ``RadioBoxGroup``. @objcMembers @objc(VDSRadioBoxItem) -open class RadioBoxItem: Control, Changeable, FormFieldable, Groupable { +open class RadioBoxItem: Control, Changeable, FormFieldable, Groupable, ParentViewProtocol { + public var children: [any ViewProtocol] { [textLabel, subTextLabel, subTextRightLabel, selectorView] } //-------------------------------------------------- // MARK: - Initializers diff --git a/VDS/Protocols/ViewProtocol.swift b/VDS/Protocols/ViewProtocol.swift index 9a509dc1..b282062a 100644 --- a/VDS/Protocols/ViewProtocol.swift +++ b/VDS/Protocols/ViewProtocol.swift @@ -9,6 +9,10 @@ import Foundation import UIKit import Combine +public protocol ParentViewProtocol { + var children: [any ViewProtocol] { get } +} + public protocol ViewProtocol: AnyObject, Initable, Resettable, Enabling, Surfaceable, AccessibilityUpdatable { /// Set of Subscribers for any Publishers for this Control. var subscribers: Set { get set } @@ -38,8 +42,15 @@ extension ViewProtocol { public func setNeedsUpdate() { if shouldUpdateView { shouldUpdateView = false + //let parent = self as? ParentViewProtocol + //parent?.children.forEach{ $0.shouldUpdateView = false } updateView() updateAccessibility() +// parent?.children.forEach{ +// $0.updateView() +// $0.updateAccessibility() +// $0.shouldUpdateView = true +// } shouldUpdateView = true } } From c41599578a99d1b58022473602c3852fbf7ecf27 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 16:03:47 -0500 Subject: [PATCH 2/4] added ParentViewProtocol to views and updated children Signed-off-by: Matt Bruce --- VDS/BaseClasses/Selector/SelectorBase.swift | 3 ++- VDS/BaseClasses/Selector/SelectorGroupBase.swift | 3 ++- VDS/BaseClasses/Selector/SelectorItemBase.swift | 5 +++-- VDS/Components/Badge/Badge.swift | 4 +++- VDS/Components/BadgeIndicator/BadgeIndicator.swift | 4 +++- VDS/Components/Breadcrumbs/Breadcrumbs.swift | 4 +++- VDS/Components/DatePicker/DatePicker.swift | 6 ++++++ VDS/Components/DropdownSelect/DropdownSelect.swift | 2 +- VDS/Components/Icon/ButtonIcon/ButtonIcon.swift | 4 +++- VDS/Components/InputStepper/InputStepper.swift | 6 ++++++ VDS/Components/Notification/Notification.swift | 4 +++- VDS/Components/PriceLockup/PriceLockup.swift | 3 ++- VDS/Components/RadioBox/RadioBoxItem.swift | 3 ++- VDS/Components/Tabs/Tabs.swift | 4 +++- VDS/Components/TextFields/EntryFieldBase.swift | 4 +++- VDS/Components/TileContainer/TileContainer.swift | 10 +++++----- VDS/Components/Tilelet/Tilelet.swift | 4 +++- VDS/Components/TitleLockup/TitleLockup.swift | 4 +++- VDS/Components/Toggle/Toggle.swift | 4 +++- VDS/Components/Tooltip/TooltipDialog.swift | 4 +++- VDS/Protocols/ViewProtocol.swift | 14 +++++++------- 21 files changed, 69 insertions(+), 30 deletions(-) diff --git a/VDS/BaseClasses/Selector/SelectorBase.swift b/VDS/BaseClasses/Selector/SelectorBase.swift index 2d12cf07..97e72afd 100644 --- a/VDS/BaseClasses/Selector/SelectorBase.swift +++ b/VDS/BaseClasses/Selector/SelectorBase.swift @@ -31,7 +31,6 @@ public protocol SelectorControlable: Control, Changeable { @objcMembers @objc(VDSSelectorBase) open class SelectorBase: Control, SelectorControlable, ParentViewProtocol { - public var children: [any ViewProtocol] { [selectorView] } //-------------------------------------------------- // MARK: - Initializers @@ -51,6 +50,8 @@ open class SelectorBase: Control, SelectorControlable, ParentViewProtocol { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [selectorView] } + open var onChangeSubscriber: AnyCancellable? open var size = CGSize(width: 20, height: 20) { didSet { setNeedsUpdate() } } diff --git a/VDS/BaseClasses/Selector/SelectorGroupBase.swift b/VDS/BaseClasses/Selector/SelectorGroupBase.swift index ebb0512b..63556c95 100644 --- a/VDS/BaseClasses/Selector/SelectorGroupBase.swift +++ b/VDS/BaseClasses/Selector/SelectorGroupBase.swift @@ -40,7 +40,6 @@ extension SelectorGroupSingleSelect { /// Base Class used for any Grouped Form Control of a Selector Type. open class SelectorGroupBase: Control, SelectorGroup, Changeable, ParentViewProtocol { - public var children: [any ViewProtocol] { items } //-------------------------------------------------- // MARK: - Private Properties @@ -58,6 +57,8 @@ open class SelectorGroupBase: Control, SelectorGrou //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { items } + /// Array of the HandlerType registered. /// Array of HandlerType that the user will have the ability to select from. open var items: [SelectorItemType] = [] { diff --git a/VDS/BaseClasses/Selector/SelectorItemBase.swift b/VDS/BaseClasses/Selector/SelectorItemBase.swift index d2ccc293..321df2a8 100644 --- a/VDS/BaseClasses/Selector/SelectorItemBase.swift +++ b/VDS/BaseClasses/Selector/SelectorItemBase.swift @@ -12,7 +12,6 @@ import VDSCoreTokens /// Base Class used to build out a SelectorControlable control. open class SelectorItemBase: Control, Errorable, Changeable, Groupable, ParentViewProtocol { - public var children: [any ViewProtocol] { [label, childLabel, errorLabel, selectorView] } //-------------------------------------------------- // MARK: - Initializers @@ -62,7 +61,9 @@ open class SelectorItemBase: Control, Errorable, Changea //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- - open var onChangeSubscriber: AnyCancellable? + open var children: [any ViewProtocol] { [label, childLabel, errorLabel, selectorView] } + + open var onChangeSubscriber: AnyCancellable? /// Label used to render labelText. open var label = Label().with { diff --git a/VDS/Components/Badge/Badge.swift b/VDS/Components/Badge/Badge.swift index 1c47133f..19c40bbc 100644 --- a/VDS/Components/Badge/Badge.swift +++ b/VDS/Components/Badge/Badge.swift @@ -17,7 +17,7 @@ import Combine /// to its parent this object will stretch to the parent's width. @objcMembers @objc(VDSBadge) -open class Badge: View { +open class Badge: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -45,6 +45,8 @@ open class Badge: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [label] } + /// Label used to render text open var label = Label().with { $0.isAccessibilityElement = false diff --git a/VDS/Components/BadgeIndicator/BadgeIndicator.swift b/VDS/Components/BadgeIndicator/BadgeIndicator.swift index daecddf4..403c7d46 100644 --- a/VDS/Components/BadgeIndicator/BadgeIndicator.swift +++ b/VDS/Components/BadgeIndicator/BadgeIndicator.swift @@ -13,7 +13,7 @@ import Combine /// A badge indicator is a visual label used to convey status or highlight supplemental information. @objcMembers @objc(VDSBadgeIndicator) -open class BadgeIndicator: View { +open class BadgeIndicator: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -135,6 +135,8 @@ open class BadgeIndicator: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [label, badgeView] } + /// Label used for the numeric kind. open var label = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) diff --git a/VDS/Components/Breadcrumbs/Breadcrumbs.swift b/VDS/Components/Breadcrumbs/Breadcrumbs.swift index 808b5548..938a22a4 100644 --- a/VDS/Components/Breadcrumbs/Breadcrumbs.swift +++ b/VDS/Components/Breadcrumbs/Breadcrumbs.swift @@ -15,11 +15,13 @@ import Combine /// Breadcrumbs are secondary navigation that use a hierarchy of internal links to tell customers where they are in an experience. Each breadcrumb links to its respective page, except for that of current page. @objcMembers @objc(VDSBreadcrumbs) -open class Breadcrumbs: View { +open class Breadcrumbs: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { breadcrumbs } + /// Array of ``BreadcrumbItem`` views for the Breadcrumbs. open var breadcrumbs: [BreadcrumbItem] = [] { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/DatePicker/DatePicker.swift b/VDS/Components/DatePicker/DatePicker.swift index e9137ad9..bd53a2a2 100644 --- a/VDS/Components/DatePicker/DatePicker.swift +++ b/VDS/Components/DatePicker/DatePicker.swift @@ -94,6 +94,12 @@ open class DatePicker: EntryFieldBase { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open override var children: [any ViewProtocol] { + var current = super.children + current.append(selectedDateLabel) + return current + } + open var calendarIcon = Icon().with { $0.name = .calendar $0.size = .medium diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 2c243a26..98a5a61f 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -31,7 +31,7 @@ open class DropdownSelect: EntryFieldBase { //-------------------------------------------------- // MARK: - Public Properties - //-------------------------------------------------- + //-------------------------------------------------- /// If true, the label will be displayed inside the dropdown containerView. Otherwise, the label will be above the dropdown containerView like a normal text input. open var showInlineLabel: Bool = false { didSet { setNeedsUpdate() }} diff --git a/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift b/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift index b6b51601..92be222d 100644 --- a/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift +++ b/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift @@ -14,7 +14,7 @@ import Combine /// It usually represents a supplementary or utilitarian action. A button icon can stand alone, but often /// exists in a group when there are several actions that can be performed. @objc(VDSButtonIcon) -open class ButtonIcon: Control, Changeable { +open class ButtonIcon: Control, Changeable, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -109,6 +109,8 @@ open class ButtonIcon: Control, Changeable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [icon] } + public var onChangeSubscriber: AnyCancellable? ///Badge Indicator object used to render for the ButtonIcon. diff --git a/VDS/Components/InputStepper/InputStepper.swift b/VDS/Components/InputStepper/InputStepper.swift index 6c44b58f..1323bd25 100644 --- a/VDS/Components/InputStepper/InputStepper.swift +++ b/VDS/Components/InputStepper/InputStepper.swift @@ -70,6 +70,12 @@ open class InputStepper: EntryFieldBase { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open override var children: [any ViewProtocol] { + var current = super.children + current.append(contentsOf: [decrementButton, incrementButton, textLabel]) + return current + } + /// If there is a width that is larger than this size's minimumWidth, the input stepper will resize to this width. open var controlWidth: ControlWidth? { get { _controlWidth } diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index 59d2b78f..0fb05caa 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -16,7 +16,7 @@ import Combine /// experience-wide. @objcMembers @objc(VDSNotification) -open class Notification: View { +open class Notification: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -101,6 +101,8 @@ open class Notification: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [typeIcon, closeButton, titleLabel, subTitleLabel, primaryButton, secondaryButton] } + /// Icon used for denoting type. open var typeIcon = Icon().with { $0.name = .infoBold diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index 990e5b76..d36fe7ee 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -11,7 +11,7 @@ import VDSCoreTokens @objcMembers @objc(VDSPriceLockup) -open class PriceLockup: View { +open class PriceLockup: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -90,6 +90,7 @@ open class PriceLockup: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [priceLockupLabel] } /// If true, the component will render as bold. open var bold: Bool = false { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/RadioBox/RadioBoxItem.swift b/VDS/Components/RadioBox/RadioBoxItem.swift index b8530363..695b1261 100644 --- a/VDS/Components/RadioBox/RadioBoxItem.swift +++ b/VDS/Components/RadioBox/RadioBoxItem.swift @@ -15,7 +15,6 @@ import VDSCoreTokens @objcMembers @objc(VDSRadioBoxItem) open class RadioBoxItem: Control, Changeable, FormFieldable, Groupable, ParentViewProtocol { - public var children: [any ViewProtocol] { [textLabel, subTextLabel, subTextRightLabel, selectorView] } //-------------------------------------------------- // MARK: - Initializers @@ -54,6 +53,8 @@ open class RadioBoxItem: Control, Changeable, FormFieldable, Groupable, ParentVi //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [textLabel, subTextLabel, subTextRightLabel, selectorView] } + open var onChangeSubscriber: AnyCancellable? /// Label used to render the text. diff --git a/VDS/Components/Tabs/Tabs.swift b/VDS/Components/Tabs/Tabs.swift index ac9e7269..fe967338 100644 --- a/VDS/Components/Tabs/Tabs.swift +++ b/VDS/Components/Tabs/Tabs.swift @@ -12,7 +12,7 @@ import VDSCoreTokens /// Tabs are organizational components that group content and allow customers to navigate its display. Use them to separate content when the content is related but doesn’t need to be compared. @objcMembers @objc(VDSTabs) -open class Tabs: View { +open class Tabs: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -84,6 +84,8 @@ open class Tabs: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { tabViews } + /// A callback when the selectedIndex changes. Passes parameters (tabIndex). open var onTabDidSelect: ((Int) -> Void)? diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index 0a815e08..8d4aeadc 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -11,7 +11,7 @@ import VDSCoreTokens import Combine /// Base Class used to build out a Input controls. -open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable { +open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -155,6 +155,8 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalVali //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [titleLabel, helperLabel, errorLabel, statusIcon] } + /// This is the view that will be wrapped with the border for userInteraction. /// The only subview of this view is the fieldStackView open var containerView = View().with { diff --git a/VDS/Components/TileContainer/TileContainer.swift b/VDS/Components/TileContainer/TileContainer.swift index b00d0388..6c695112 100644 --- a/VDS/Components/TileContainer/TileContainer.swift +++ b/VDS/Components/TileContainer/TileContainer.swift @@ -44,7 +44,7 @@ open class TileContainer: TileContainerBase { } } -open class TileContainerBase: View where PaddingType.ValueType == CGFloat { +open class TileContainerBase: View where PaddingType.ValueType == CGFloat { //-------------------------------------------------- // MARK: - Initializers @@ -122,7 +122,7 @@ open class TileContainerBase: View where //-------------------------------------------------- // MARK: - Public Properties - //-------------------------------------------------- + //-------------------------------------------------- /// This takes an image source url and applies it as a background image. open var backgroundImage: UIImage? { didSet { setNeedsUpdate() } } @@ -340,21 +340,21 @@ open class TileContainerBase: View where open override func touchesBegan(_ touches: Set, with event: UIEvent?) { super.touchesBegan(touches, with: event) - if let onClickSubscriber { + if onClickSubscriber != nil { isHighlighted = true } } open override func touchesEnded(_ touches: Set, with event: UIEvent?) { super.touchesEnded(touches, with: event) - if let onClickSubscriber { + if onClickSubscriber != nil { isHighlighted = false } } open override func touchesCancelled(_ touches: Set, with event: UIEvent?) { super.touchesCancelled(touches, with: event) - if let onClickSubscriber { + if onClickSubscriber != nil { isHighlighted = false } } diff --git a/VDS/Components/Tilelet/Tilelet.swift b/VDS/Components/Tilelet/Tilelet.swift index cb154056..3a6e0150 100644 --- a/VDS/Components/Tilelet/Tilelet.swift +++ b/VDS/Components/Tilelet/Tilelet.swift @@ -17,7 +17,7 @@ import Combine /// function. @objcMembers @objc(VDSTilelet) -open class Tilelet: TileContainerBase { +open class Tilelet: TileContainerBase, ParentViewProtocol { /// Enum used to describe the padding choices used for this component. public enum Padding: String, DefaultValuing, Valuing, CaseIterable { @@ -110,6 +110,8 @@ open class Tilelet: TileContainerBase { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [badge, titleLockup, descriptiveIcon, directionalIcon] } + /// Title lockup positioned in the contentView. open var titleLockup = TitleLockup().with { $0.standardStyleConfiguration = .init(styleConfigurations: [ diff --git a/VDS/Components/TitleLockup/TitleLockup.swift b/VDS/Components/TitleLockup/TitleLockup.swift index 1711939c..ad56813b 100644 --- a/VDS/Components/TitleLockup/TitleLockup.swift +++ b/VDS/Components/TitleLockup/TitleLockup.swift @@ -14,7 +14,7 @@ import Combine /// with approved built in text size configurations. @objcMembers @objc(VDSTitleLockup) -open class TitleLockup: View { +open class TitleLockup: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -62,6 +62,8 @@ open class TitleLockup: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [eyebrowLabel, titleLabel, subTitleLabel] } + /// Aligns TitleLockup's subcomponent's text open var textAlignment: TextAlignment = .left { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/Toggle/Toggle.swift b/VDS/Components/Toggle/Toggle.swift index 304b18ce..8c11004b 100644 --- a/VDS/Components/Toggle/Toggle.swift +++ b/VDS/Components/Toggle/Toggle.swift @@ -14,7 +14,7 @@ import Combine /// or turn off a single option, setting or function. @objcMembers @objc(VDSToggle) -open class Toggle: Control, Changeable, FormFieldable { +open class Toggle: Control, Changeable, FormFieldable, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -90,6 +90,8 @@ open class Toggle: Control, Changeable, FormFieldable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [toggleView, label] } + open var onChangeSubscriber: AnyCancellable? /// Actual toggle used in this component. diff --git a/VDS/Components/Tooltip/TooltipDialog.swift b/VDS/Components/Tooltip/TooltipDialog.swift index bb6b5653..bbccb8f5 100644 --- a/VDS/Components/Tooltip/TooltipDialog.swift +++ b/VDS/Components/Tooltip/TooltipDialog.swift @@ -11,7 +11,7 @@ import VDSCoreTokens @objcMembers @objc(VDSTooltipDialog) -open class TooltipDialog: View, UIScrollViewDelegate { +open class TooltipDialog: View, UIScrollViewDelegate, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -55,6 +55,8 @@ open class TooltipDialog: View, UIScrollViewDelegate { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [titleLabel, contentLabel] } + open var tooltipModel = Tooltip.TooltipModel() { didSet { setNeedsUpdate() } } open var titleLabel = Label().with { label in diff --git a/VDS/Protocols/ViewProtocol.swift b/VDS/Protocols/ViewProtocol.swift index b282062a..e38d5df4 100644 --- a/VDS/Protocols/ViewProtocol.swift +++ b/VDS/Protocols/ViewProtocol.swift @@ -42,15 +42,15 @@ extension ViewProtocol { public func setNeedsUpdate() { if shouldUpdateView { shouldUpdateView = false - //let parent = self as? ParentViewProtocol - //parent?.children.forEach{ $0.shouldUpdateView = false } + let parent = self as? ParentViewProtocol + parent?.children.forEach{ $0.shouldUpdateView = false } updateView() updateAccessibility() -// parent?.children.forEach{ -// $0.updateView() -// $0.updateAccessibility() -// $0.shouldUpdateView = true -// } + parent?.children.forEach{ + $0.updateView() + $0.updateAccessibility() + $0.shouldUpdateView = true + } shouldUpdateView = true } } From 952d688cc2729fa8f16710bc5668b743e4eda0fe Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 23 Aug 2024 08:35:36 -0500 Subject: [PATCH 3/4] updated with traversal Signed-off-by: Matt Bruce --- VDS/Protocols/ViewProtocol.swift | 34 ++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/VDS/Protocols/ViewProtocol.swift b/VDS/Protocols/ViewProtocol.swift index e38d5df4..4eb091b1 100644 --- a/VDS/Protocols/ViewProtocol.swift +++ b/VDS/Protocols/ViewProtocol.swift @@ -9,10 +9,28 @@ import Foundation import UIKit import Combine -public protocol ParentViewProtocol { +public protocol ParentViewProtocol: ViewProtocol { var children: [any ViewProtocol] { get } } +extension ParentViewProtocol { + public func getAllChildren() -> [any ViewProtocol] { + var allChildren = [any ViewProtocol]() + + func traverse(view: any ViewProtocol) { + if let parentView = view as? any ParentViewProtocol { + for child in parentView.children { + allChildren.append(child) + traverse(view: child) + } + } + } + + traverse(view: self) + return children + } +} + public protocol ViewProtocol: AnyObject, Initable, Resettable, Enabling, Surfaceable, AccessibilityUpdatable { /// Set of Subscribers for any Publishers for this Control. var subscribers: Set { get set } @@ -42,11 +60,19 @@ extension ViewProtocol { public func setNeedsUpdate() { if shouldUpdateView { shouldUpdateView = false - let parent = self as? ParentViewProtocol - parent?.children.forEach{ $0.shouldUpdateView = false } + + //see if this is a view that has children + let parent = self as? any ParentViewProtocol + let children = parent?.getAllChildren() + //if so turn off the shouldUpdate to keep UI + //from blocking + children?.forEach{ $0.shouldUpdateView = false } + updateView() updateAccessibility() - parent?.children.forEach{ + + //if so turn on + children?.forEach{ $0.updateView() $0.updateAccessibility() $0.shouldUpdateView = true From b3f602087d3c9691ec3efcce9d24def3713e797d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 23 Aug 2024 08:39:18 -0500 Subject: [PATCH 4/4] refactored into a new file with traversal Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 4 +++ VDS/Protocols/ParentViewProtocol.swift | 37 ++++++++++++++++++++++++++ VDS/Protocols/ViewProtocol.swift | 22 --------------- 3 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 VDS/Protocols/ParentViewProtocol.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index fc3417d2..34b75bda 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -101,6 +101,7 @@ EA6642952BCEBF9500D81DC4 /* TextLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642942BCEBF9500D81DC4 /* TextLinkModel.swift */; }; EA6F330E2B911E9000BACAB9 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6F330D2B911E9000BACAB9 /* TextView.swift */; }; EA78C7962C00CAC200430AD1 /* Groupable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA78C7952C00CAC200430AD1 /* Groupable.swift */; }; + EA7AE5592C78C7D000107C74 /* ParentViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5582C78C7D000107C74 /* ParentViewProtocol.swift */; }; EA81410B2A0E8E3C004F60D2 /* ButtonIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */; }; EA8141102A127066004F60D2 /* UIColor+VDSColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410F2A127066004F60D2 /* UIColor+VDSColor.swift */; }; EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */; }; @@ -323,6 +324,7 @@ EA78C7952C00CAC200430AD1 /* Groupable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Groupable.swift; sourceTree = ""; }; EA78C7A12C0E63D200430AD1 /* vds-dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "vds-dev.xcconfig"; sourceTree = ""; }; EA78C7A22C0E63DD00430AD1 /* vds.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = vds.xcconfig; sourceTree = ""; }; + EA7AE5582C78C7D000107C74 /* ParentViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentViewProtocol.swift; sourceTree = ""; }; EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIcon.swift; sourceTree = ""; }; EA81410F2A127066004F60D2 /* UIColor+VDSColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+VDSColor.swift"; sourceTree = ""; }; EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextField+Publisher.swift"; sourceTree = ""; }; @@ -777,6 +779,7 @@ EA78C7952C00CAC200430AD1 /* Groupable.swift */, EA33624628931B050071C351 /* Initable.swift */, EA471F392A95587500CE9E58 /* LayoutConstraintable.swift */, + EA7AE5582C78C7D000107C74 /* ParentViewProtocol.swift */, EA985C7C297DAED300F2FF2E /* Primitive.swift */, EAF7F0A5289B0CE000B287F5 /* Resetable.swift */, EA3361C8289054C50071C351 /* Surfaceable.swift */, @@ -1335,6 +1338,7 @@ EAF7F0A4289B017C00B287F5 /* LabelAttributeModel.swift in Sources */, EA0B18022A9E236900F2D0CD /* SelectorGroupBase.swift in Sources */, EA5F86D02A1F936100BC83E4 /* TabsContainer.swift in Sources */, + EA7AE5592C78C7D000107C74 /* ParentViewProtocol.swift in Sources */, EAF7F0B1289B177F00B287F5 /* ColorLabelAttribute.swift in Sources */, EAC9258F2911C9DE00091998 /* EntryFieldBase.swift in Sources */, 18B9763F2C11BA4A009271DF /* CarouselPaginationModel.swift in Sources */, diff --git a/VDS/Protocols/ParentViewProtocol.swift b/VDS/Protocols/ParentViewProtocol.swift new file mode 100644 index 00000000..b4c07863 --- /dev/null +++ b/VDS/Protocols/ParentViewProtocol.swift @@ -0,0 +1,37 @@ +// +// ParentViewProtocol.swift +// VDS +// +// Created by Matt Bruce on 8/23/24. +// + +import Foundation + + +/// This is used in a View or Control to denote subviews of the ViewProtocol +/// type, more or less for composite views/controls. +public protocol ParentViewProtocol: ViewProtocol { + var children: [any ViewProtocol] { get } +} + +extension ParentViewProtocol { + + /// This will get all of the children for yourself as well as all + /// of the children within the full tree hierarchy. + /// - Returns: All children within the hierachy + public func getAllChildren() -> [any ViewProtocol] { + var allChildren = [any ViewProtocol]() + + func traverse(view: any ViewProtocol) { + if let parentView = view as? any ParentViewProtocol { + for child in parentView.children { + allChildren.append(child) + traverse(view: child) + } + } + } + + traverse(view: self) + return children + } +} diff --git a/VDS/Protocols/ViewProtocol.swift b/VDS/Protocols/ViewProtocol.swift index 4eb091b1..6d3dc4f3 100644 --- a/VDS/Protocols/ViewProtocol.swift +++ b/VDS/Protocols/ViewProtocol.swift @@ -9,28 +9,6 @@ import Foundation import UIKit import Combine -public protocol ParentViewProtocol: ViewProtocol { - var children: [any ViewProtocol] { get } -} - -extension ParentViewProtocol { - public func getAllChildren() -> [any ViewProtocol] { - var allChildren = [any ViewProtocol]() - - func traverse(view: any ViewProtocol) { - if let parentView = view as? any ParentViewProtocol { - for child in parentView.children { - allChildren.append(child) - traverse(view: child) - } - } - } - - traverse(view: self) - return children - } -} - public protocol ViewProtocol: AnyObject, Initable, Resettable, Enabling, Surfaceable, AccessibilityUpdatable { /// Set of Subscribers for any Publishers for this Control. var subscribers: Set { get set }