From 3d303e6c0788611ba7a9cd34516b745b37fb1451 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 15 Feb 2024 10:54:42 -0600 Subject: [PATCH 1/5] allow overriding Signed-off-by: Matt Bruce --- VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift b/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift index 113d19f5..ddb5d617 100644 --- a/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift +++ b/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift @@ -198,7 +198,7 @@ extension ButtonGroup: UICollectionViewDataSource, UICollectionViewDelegate { return buttons.count } - public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let button = buttons[indexPath.row] guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as? ButtonGroupCollectionViewCell else { return UICollectionViewCell() } cell.contentView.subviews.forEach { $0.removeFromSuperview() } From abb94257da8d8045e1d88f92e10c4195dd43fac1 Mon Sep 17 00:00:00 2001 From: Krishna Kishore Bandaru Date: Mon, 26 Feb 2024 13:28:24 +0530 Subject: [PATCH 2/5] fixed conflicting constraints --- VDS/Components/Notification/Notification.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index 2ed84116..126f83f0 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -398,13 +398,18 @@ open class Notification: View { } private func setConstraints() { + maxWidthConstraint?.deactivate() + labelViewAndButtonViewConstraint?.deactivate() + labelViewBottomConstraint?.deactivate() + buttonGroupCenterYConstraint?.deactivate() + buttonGroupBottomConstraint?.deactivate() maxWidthConstraint?.constant = maxViewWidth maxWidthConstraint?.isActive = UIDevice.isIPad labelViewAndButtonViewConstraint?.isActive = layout == .vertical && !buttonGroup.buttons.isEmpty - typeIconWidthConstraint?.constant = typeIcon.size.dimensions.width - closeIconWidthConstraint?.constant = closeButton.size.dimensions.width labelViewBottomConstraint?.isActive = layout == .horizontal || buttonGroup.buttons.isEmpty buttonGroupCenterYConstraint?.isActive = layout == .horizontal buttonGroupBottomConstraint?.isActive = layout == .vertical + typeIconWidthConstraint?.constant = typeIcon.size.dimensions.width + closeIconWidthConstraint?.constant = closeButton.size.dimensions.width } } From 11c8ed87565c85e2c4979ff5962c6e461b902d62 Mon Sep 17 00:00:00 2001 From: "Bandaru, Krishna Kishore" Date: Mon, 26 Feb 2024 21:10:53 +0000 Subject: [PATCH 3/5] Fixed conflicting constraints while displaying Notifications --- VDS/Components/Notification/Notification.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index 2ed84116..126f83f0 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -398,13 +398,18 @@ open class Notification: View { } private func setConstraints() { + maxWidthConstraint?.deactivate() + labelViewAndButtonViewConstraint?.deactivate() + labelViewBottomConstraint?.deactivate() + buttonGroupCenterYConstraint?.deactivate() + buttonGroupBottomConstraint?.deactivate() maxWidthConstraint?.constant = maxViewWidth maxWidthConstraint?.isActive = UIDevice.isIPad labelViewAndButtonViewConstraint?.isActive = layout == .vertical && !buttonGroup.buttons.isEmpty - typeIconWidthConstraint?.constant = typeIcon.size.dimensions.width - closeIconWidthConstraint?.constant = closeButton.size.dimensions.width labelViewBottomConstraint?.isActive = layout == .horizontal || buttonGroup.buttons.isEmpty buttonGroupCenterYConstraint?.isActive = layout == .horizontal buttonGroupBottomConstraint?.isActive = layout == .vertical + typeIconWidthConstraint?.constant = typeIcon.size.dimensions.width + closeIconWidthConstraint?.constant = closeButton.size.dimensions.width } } From 9e91f38c52475851f072a4291dc891968904b3e3 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 26 Feb 2024 17:50:47 -0600 Subject: [PATCH 4/5] added "text" as a property Signed-off-by: Matt Bruce --- VDS/Components/TextFields/EntryFieldBase.swift | 6 ++++++ VDS/Components/TextFields/InputField/InputField.swift | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index dcb16fbf..e66d31a5 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -180,6 +180,12 @@ open class EntryFieldBase: Control, Changeable { } } + /// Override this to conveniently get/set the textfield(s). + open var text: String? { + get { nil } + set { fatalError("You MUST override EntryField's 'text' variable in your subclass.") } + } + open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } } open var transparentBackground: Bool = false { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/TextFields/InputField/InputField.swift b/VDS/Components/TextFields/InputField/InputField.swift index 94ef5231..589ba28f 100644 --- a/VDS/Components/TextFields/InputField/InputField.swift +++ b/VDS/Components/TextFields/InputField/InputField.swift @@ -78,6 +78,14 @@ open class InputField: EntryFieldBase, UITextFieldDelegate { /// Representing the type of input. open var fieldType: FieldType = .text { didSet { setNeedsUpdate() } } + /// The text of this textField. + open override var text: String? { + get { textField.text } + set { + textField.text = newValue + } + } + var _showError: Bool = false /// Whether not to show the error. open override var showError: Bool { From 6d38474675932ac6cf855e88aa59d82e5c5090cb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 26 Feb 2024 17:51:16 -0600 Subject: [PATCH 5/5] added text as a property added subclass of UITextField to deal with text rendering and attributes. Signed-off-by: Matt Bruce --- .../TextFields/TextArea/TextArea.swift | 179 ++++++++++++++++-- 1 file changed, 164 insertions(+), 15 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index a9c1cbf4..e9da9b11 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -107,20 +107,21 @@ open class TextArea: EntryFieldBase { } } + /// The text of this textField. + open override var text: String? { + get { textView.text } + set { + textView.text = newValue + } + } + /// UITextView shown in the TextArea. - open var textView = UITextView().with { + open var textView = TextView().with { $0.translatesAutoresizingMaskIntoConstraints = false - $0.font = TextStyle.bodyLarge.font $0.sizeToFit() $0.isScrollEnabled = false } - /// Color configuration for the textView. - open var textViewTextColorConfiguration: AnyColorable = ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) - $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) - }.eraseToAnyColorable() { didSet { setNeedsUpdate() } } - /// Color configuration for error icon. internal var iconColorConfiguration = ControlColorConfiguration().with { $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal) @@ -187,7 +188,9 @@ open class TextArea: EntryFieldBase { super.updateView() textView.isEditable = isEnabled - textView.textColor = textViewTextColorConfiguration.getColor(self) + textView.isEnabled = isEnabled + textView.surface = surface + //set the width constraints if let width { widthConstraint?.constant = width @@ -260,12 +263,18 @@ open class TextArea: EntryFieldBase { open func highlightCharacterOverflow() { let count = textView.text.count - guard let maxLength, - count > maxLength, - let text = textView.attributedText?.mutableCopy() as? NSMutableAttributedString else { return } - text.addAttribute(NSAttributedString.Key.backgroundColor, value: highlightBackgroundColor.getColor(self), range: NSRange(location:maxLength, length: (count - maxLength))) - text.addAttribute(NSAttributedString.Key.foregroundColor, value: highlightTextColor.getColor(self), range: NSRange(location:maxLength, length: (count - maxLength))) - textView.attributedText = text + guard let maxLength, count > maxLength else { + textView.textAttributes = nil + return + } + + var textAttributes = [any LabelAttributeModel]() + let location = maxLength + let length = count - maxLength + textAttributes.append(ColorLabelAttribute(location: location, length: length, color: highlightBackgroundColor.getColor(self), isForegroundColor: false)) + textAttributes.append(ColorLabelAttribute(location: location, length: length, color: highlightTextColor.getColor(self), isForegroundColor: true)) + + textView.textAttributes = textAttributes } } @@ -310,3 +319,143 @@ extension TextArea: UITextViewDelegate { } } } + +/// Will move this into a new file, need to talk with Scott/Kyle +open class TextView: UITextView, ViewProtocol { + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + required public init() { + super.init(frame: .zero, textContainer: nil) + initialSetup() + } + + public override init(frame: CGRect, textContainer: NSTextContainer?) { + super.init(frame: frame, textContainer: textContainer) + initialSetup() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + initialSetup() + } + + //-------------------------------------------------- + // MARK: - Combine Properties + //-------------------------------------------------- + /// Set of Subscribers for any Publishers for this Control. + open var subscribers = Set() + + //-------------------------------------------------- + // MARK: - Private Properties + //-------------------------------------------------- + private var initialSetupPerformed = false + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + /// Key of whether or not updateView() is called in setNeedsUpdate() + open var shouldUpdateView: Bool = true + + open var surface: Surface = .light { didSet { setNeedsUpdate() } } + + /// Array of LabelAttributeModel objects used in rendering the text. + open var textAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() } } + + /// TextStyle used on the titleLabel. + open var textStyle: TextStyle { .defaultStyle } + + /// Will determine if a scaled font should be used for the titleLabel font. + open var useScaledFont: Bool = false { didSet { setNeedsUpdate() } } + + open var isEnabled: Bool = true { didSet { setNeedsUpdate() } } + + open var textColorConfiguration: AnyColorable = ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) + }.eraseToAnyColorable(){ didSet { setNeedsUpdate() }} + + open override var textColor: UIColor? { + get { textColorConfiguration.getColor(self) } + set { } + } + + override public var text: String! { + get { super.text } + set { + super.text = newValue + updateLabel() + } + } + + override public var textAlignment: NSTextAlignment { + didSet { + if textAlignment != oldValue { + // Text alignment can be part of our paragraph style, so we may need to + // re-style when changed + updateLabel() + } + } + } + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + open func initialSetup() { + if !initialSetupPerformed { + backgroundColor = .clear + translatesAutoresizingMaskIntoConstraints = false + accessibilityCustomActions = [] + setup() + setNeedsUpdate() + } + } + + + open func setup() { + translatesAutoresizingMaskIntoConstraints = false + } + + open func updateView() { + updateLabel() + } + + open func updateAccessibility() {} + + open func reset() { + shouldUpdateView = false + surface = .light + text = nil + accessibilityCustomActions = [] + shouldUpdateView = true + setNeedsUpdate() + } + + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- + private func updateLabel() { + + //clear the arrays holding actions + accessibilityCustomActions = [] + if let text, !text.isEmpty { + //create the primary string + let mutableText = NSMutableAttributedString.mutableText(for: text, + textStyle: textStyle, + useScaledFont: useScaledFont, + textColor: textColor!, + alignment: textAlignment, + lineBreakMode: .byWordWrapping) + //apply any attributes + if let attributes = textAttributes { + mutableText.apply(attributes: attributes) + } + attributedText = mutableText + } else { + attributedText = nil + } + } + + +}