From 05674a67980a7dc89aec4671c4428c6fb430523f Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 7 Jan 2022 12:54:28 -0600 Subject: [PATCH] added isReadOnly to views/helpers to read the model.readOnly property and update the UI similarly to disabled state Signed-off-by: Matt Bruce --- .../TextFields/DigitEntryField.swift | 8 ++++++++ .../BaseDropdownEntryField.swift | 8 ++++++++ .../FormFields/TextFields/EntryField.swift | 14 +++++++++++++ .../TextFields/TextEntryField.swift | 16 ++++++++++++++- .../TextFields/TextViewEntryField.swift | 20 ++++++++++++++++++- .../Atomic/Atoms/Selectors/Checkbox.swift | 20 +++++++++++++++++-- MVMCoreUI/Atomic/Atoms/Selectors/Heart.swift | 9 +++++---- .../Atomic/Atoms/Selectors/RadioBox.swift | 11 +++++++--- .../Atomic/Atoms/Selectors/RadioButton.swift | 5 +++-- .../RadioButtonSelectionHelper.swift | 4 +++- MVMCoreUI/Atomic/Atoms/Selectors/Toggle.swift | 13 ++++++++++-- .../CarouselIndicator/BarsIndicatorView.swift | 16 +++++++++++++-- .../NumericIndicatorView.swift | 6 +++++- MVMCoreUI/BaseClasses/Control.swift | 9 ++++++++- .../Views/EntryFieldContainer.swift | 15 ++++++++++++++ 15 files changed, 154 insertions(+), 20 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/DigitEntryField.swift index c70d458e..f3fa96ba 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/DigitEntryField.swift @@ -90,6 +90,14 @@ import UIKit } } + public override var isReadOnly: Bool { + get { super.isReadOnly } + set (readOnly){ + digitBoxes.forEach { $0.isReadOnly = readOnly } + super.isReadOnly = readOnly + } + } + public override var showError: Bool { get { super.showError } set (error) { diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/BaseDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/BaseDropdownEntryField.swift index d9b42a41..f70b0ce0 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/BaseDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/BaseDropdownEntryField.swift @@ -45,6 +45,14 @@ import UIKit } } + @objc public override var isReadOnly: Bool { + get { super.isReadOnly } + set (readOnly) { + dropDownCaretView.isEnabled = !readOnly + super.isReadOnly = readOnly + } + } + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 147f6f5f..c858fbda 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -66,6 +66,19 @@ import UIKit } } + /// Toggles readOnly (original) or disabled UI. + public var isReadOnly: Bool { + get { entryFieldContainer.isReadOnly } + set (readOnly) { + if(entryFieldContainer.isReadOnly != readOnly){ + titleLabel.isEnabled = !readOnly + feedbackLabel.isEnabled = !readOnly + entryFieldContainer.isReadOnly = readOnly + entryFieldModel?.readOnly = readOnly + } + } + } + /// Toggles error or original UI. public var showError: Bool { get { entryFieldContainer.showError } @@ -315,6 +328,7 @@ import UIKit defaultText = model.text ?? "" isEnabled = model.enabled + isReadOnly = model.readOnly model.updateUI = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { guard let self = self else { return } diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift index 7973d652..6c8d8116 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift @@ -69,7 +69,21 @@ import UIKit guard let self = self else { return } self.textField.isEnabled = enabled - self.textField.textColor = enabled ? self.textEntryFieldModel?.enabledTextColor.uiColor : self.textEntryFieldModel?.disabledTextColor.uiColor + self.textField.textColor = enabled && !self.isReadOnly ? self.textEntryFieldModel?.enabledTextColor.uiColor : self.textEntryFieldModel?.disabledTextColor.uiColor + } + } + } + + public override var isReadOnly: Bool { + get { super.isReadOnly } + set (readOnly) { + super.isReadOnly = readOnly + + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + + self.textField.isEnabled = !readOnly + self.textField.textColor = !readOnly ? self.textEntryFieldModel?.enabledTextColor.uiColor : self.textEntryFieldModel?.disabledTextColor.uiColor } } } diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift index 543469c1..8c1cafa8 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift @@ -46,7 +46,25 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele if self.textView.isShowingPlaceholder { self.textView.textColor = self.textView.placeholderTextColor } else { - self.textView.textColor = (enabled ? self.textViewEntryFieldModel?.enabledTextColor : self.textViewEntryFieldModel?.disabledTextColor)?.uiColor + self.textView.textColor = (enabled && !self.isReadOnly ? self.textViewEntryFieldModel?.enabledTextColor : self.textViewEntryFieldModel?.disabledTextColor)?.uiColor + } + } + } + } + + public override var isReadOnly: Bool { + get { super.isReadOnly } + set (readOnly) { + super.isReadOnly = readOnly + + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + + self.textView.isEnabled = !readOnly + if self.textView.isShowingPlaceholder { + self.textView.textColor = self.textView.placeholderTextColor + } else { + self.textView.textColor = (!readOnly ? self.textViewEntryFieldModel?.enabledTextColor : self.textViewEntryFieldModel?.disabledTextColor)?.uiColor } } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/Checkbox.swift b/MVMCoreUI/Atomic/Atoms/Selectors/Checkbox.swift index 4481411e..8fbb2bea 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/Checkbox.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/Checkbox.swift @@ -84,7 +84,7 @@ import MVMCore isUserInteractionEnabled = isEnabled - if isEnabled { + if isEnabled && !self.isReadOnly { layer.borderColor = borderColor.cgColor backgroundColor = isSelected ? checkedBackgroundColor : unCheckedBackgroundColor setShapeLayerStrokeColor(checkColor) @@ -96,6 +96,20 @@ import MVMCore } } + public override var isReadOnly: Bool { + didSet{ + if isReadOnly { + layer.borderColor = disabledBorderColor.cgColor + backgroundColor = disabledBackgroundColor + setShapeLayerStrokeColor(disabledCheckColor) + } else { + layer.borderColor = borderColor.cgColor + backgroundColor = isSelected ? checkedBackgroundColor : unCheckedBackgroundColor + setShapeLayerStrokeColor(checkColor) + } + } + } + public var disabledBackgroundColor: UIColor = .clear public var disabledBorderColor: UIColor = .mvmCoolGray3 public var disabledCheckColor: UIColor = .mvmCoolGray3 @@ -239,7 +253,7 @@ import MVMCore self.shapeLayer = shapeLayer shapeLayer.frame = bounds layer.addSublayer(shapeLayer) - shapeLayer.strokeColor = isEnabled ? checkColor.cgColor : disabledCheckColor.cgColor + shapeLayer.strokeColor = isEnabled || !isReadOnly ? checkColor.cgColor : disabledCheckColor.cgColor shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.path = checkMarkPath() shapeLayer.lineJoin = .miter @@ -368,6 +382,7 @@ import MVMCore super.reset() isEnabled = true + isReadOnly = false shapeLayer?.removeAllAnimations() shapeLayer?.removeFromSuperlayer() shapeLayer = nil @@ -431,6 +446,7 @@ import MVMCore } isEnabled = model.enabled + isReadOnly = model.readOnly if (model.action != nil || model.offAction != nil) { actionBlock = { [weak self] in diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/Heart.swift b/MVMCoreUI/Atomic/Atoms/Selectors/Heart.swift index e694e194..cd423dca 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/Heart.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/Heart.swift @@ -62,7 +62,7 @@ import UIKit heartPath.close() heart.path = heartPath.cgPath heart.fillColor = isSelected ? heartModel?.activeColor.cgColor : heartModel?.inActiveColor.cgColor - heart.opacity = 1.0 + heart.opacity = isEnabled || !isReadOnly ? 1.0 : 0.5 heart.lineWidth = 1 heart.strokeColor = isSelected ? UIColor.clear.cgColor : UIColor.mvmBlack.cgColor return heart @@ -89,6 +89,7 @@ import UIKit guard let model = model as? HeartModel else { return } isSelected = model.isActive isEnabled = model.enabled + isReadOnly = model.readOnly updateAccessibilityLabel() } @@ -97,13 +98,13 @@ import UIKit //-------------------------------------------------- /// Adjust accessibility label based on selection of Heart. func updateAccessibilityLabel() { - accessibilityHint = isEnabled ? MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "heart_unfavorite_action_hint" : "heart_favorite_action_hint") : nil - accessibilityTraits = isEnabled ? .button : .none + accessibilityHint = isEnabled || !isReadOnly ? MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "heart_unfavorite_action_hint" : "heart_favorite_action_hint") : nil + accessibilityTraits = isEnabled || !isReadOnly ? .button : .none accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "heart_selected_state" : "heart_not_selected_state") } func tapAction() { - guard isEnabled else { return } + guard isEnabled, !isReadOnly else { return } isSelected = !isSelected if let heartModel = heartModel { Button.performButtonAction(with: heartModel.action, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: heartModel) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift index 1d8c6960..693fe2a4 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift @@ -40,6 +40,10 @@ open class RadioBox: Control, MFButtonProtocol { didSet { updateAccessibility() } } + public override var isReadOnly: Bool { + didSet { updateAccessibility() } + } + //-------------------------------------------------- // MARK: - MVMCoreViewProtocol //-------------------------------------------------- @@ -90,6 +94,7 @@ open class RadioBox: Control, MFButtonProtocol { } isSelected = model.selected isEnabled = model.enabled + isReadOnly = model.readOnly } open override func reset() { @@ -124,7 +129,7 @@ open class RadioBox: Control, MFButtonProtocol { // Handle Mask maskLayer?.removeFromSuperlayer() - if !isEnabled { + if !isEnabled || isReadOnly { let mask = getMaskLayer() layer.mask = mask maskLayer = mask @@ -138,7 +143,7 @@ open class RadioBox: Control, MFButtonProtocol { } @objc open func selectBox() { - guard isEnabled, !isSelected else { return } + guard isEnabled, !isReadOnly, !isSelected else { return } isSelected = true radioBoxModel?.selected = isSelected if let radioBoxModel = radioBoxModel, let actionModel = radioBoxModel.action { @@ -237,7 +242,7 @@ open class RadioBox: Control, MFButtonProtocol { accessibilityTraits.insert(.selected) } - if !isEnabled { + if !isEnabled || isReadOnly { accessibilityTraits.insert(.notEnabled) } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index c6e1e049..11b917b0 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -66,7 +66,7 @@ import UIKit open override func draw(_ rect: CGRect) { guard let context = UIGraphicsGetCurrentContext() else { return } - let color = isEnabled ? enabledColor.cgColor : disabledColor.cgColor + let color = (isReadOnly == true || isEnabled == false) ? disabledColor.cgColor : enabledColor.cgColor layer.cornerRadius = bounds.width * 0.5 layer.borderColor = color layer.borderWidth = bounds.width * 0.0333 @@ -88,7 +88,7 @@ import UIKit /// The action performed when tapped. func tapAction() { - if !isEnabled { + if !isEnabled || isReadOnly { return } @@ -164,6 +164,7 @@ import UIKit isSelected = model.state isEnabled = model.enabled + isReadOnly = model.readOnly RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject) } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift index 41f709c0..da7ef0c2 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift @@ -18,7 +18,8 @@ private var selectedRadioButtonModel: RadioButtonModel? public var baseValue: AnyHashable? public var enabled: Bool = true - + public var readOnly: Bool = false + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -41,6 +42,7 @@ radioButton.isSelected = false } self.enabled = radioButtonModel.enabled + self.readOnly = radioButtonModel.readOnly } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Selectors/Toggle.swift index 3513a03b..a76424f0 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/Toggle.swift @@ -67,6 +67,14 @@ public typealias ActionBlockConfirmation = () -> (Bool) } } + public override var isReadOnly: Bool { + didSet{ + changeStateNoAnimation(!isReadOnly ? isOn : false) + setToggleAppearanceFromState() + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: !isReadOnly ? "AccToggleHint" : "AccDisabled") + } + } + /// Simple means to prevent user interaction with the toggle. public var isLocked: Bool = false { didSet { isUserInteractionEnabled = !isLocked } @@ -350,8 +358,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) public func setToggleAppearanceFromState() { - backgroundColor = isEnabled ? isOn ? containerTintColor.on : containerTintColor.off : disabledTintColor.container - knobView.backgroundColor = isEnabled ? isOn ? knobTintColor.on : knobTintColor.off : disabledTintColor.knob + backgroundColor = isEnabled || !isReadOnly ? isOn ? containerTintColor.on : containerTintColor.off : disabledTintColor.container + knobView.backgroundColor = isEnabled || !isReadOnly ? isOn ? knobTintColor.on : knobTintColor.off : disabledTintColor.knob } public func knobReformAnimation() { @@ -385,6 +393,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) changeStateNoAnimation(isOn) isAnimated = model.animated isEnabled = model.enabled + isReadOnly = model.readOnly if let accessibileString = model.accessibilityText { accessibilityLabel = accessibileString diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift index 975c7ebb..1f2e7346 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift @@ -72,9 +72,21 @@ open class BarsIndicatorView: CarouselIndicator { didSet { for (i, indicatorBar) in barReferences.enumerated() { if i == currentIndex { - indicatorBar.backgroundColor = isEnabled ? currentIndicatorColor : disabledIndicatorColor + indicatorBar.backgroundColor = isEnabled && !isReadOnly ? currentIndicatorColor : disabledIndicatorColor } else { - indicatorBar.backgroundColor = isEnabled ? indicatorColor : disabledIndicatorColor + indicatorBar.backgroundColor = isEnabled && !isReadOnly ? indicatorColor : disabledIndicatorColor + } + } + } + } + + open override var isReadOnly: Bool { + didSet { + for (i, indicatorBar) in barReferences.enumerated() { + if i == currentIndex { + indicatorBar.backgroundColor = !isReadOnly ? currentIndicatorColor : disabledIndicatorColor + } else { + indicatorBar.backgroundColor = !isReadOnly ? indicatorColor : disabledIndicatorColor } } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift index eb3a8ebd..e888fff8 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift @@ -42,7 +42,11 @@ open class NumericIndicatorView: CarouselIndicator { //-------------------------------------------------- open override var isEnabled: Bool { - didSet { setViewColor(isEnabled ? indicatorColor : disabledIndicatorColor) } + didSet { setViewColor(isEnabled && !isReadOnly ? indicatorColor : disabledIndicatorColor) } + } + + open override var isReadOnly: Bool { + didSet { setViewColor(!isReadOnly ? indicatorColor : disabledIndicatorColor) } } /// Sets the color for pageCount text, left arrow and right arrow. diff --git a/MVMCoreUI/BaseClasses/Control.swift b/MVMCoreUI/BaseClasses/Control.swift index a8fde2e5..3aebaf7e 100644 --- a/MVMCoreUI/BaseClasses/Control.swift +++ b/MVMCoreUI/BaseClasses/Control.swift @@ -13,7 +13,14 @@ import UIKit //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - + public var isReadOnly: Bool = false{ + didSet{ + //don't allow touches + isUserInteractionEnabled = !isReadOnly + setNeedsDisplay() + } + } + open var model: MoleculeModelProtocol? private var initialSetupPerformed = false diff --git a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift index 9ccd1d25..f567d01f 100644 --- a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift +++ b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift @@ -55,6 +55,7 @@ import UIKit private var _showError: Bool = false private var _isLocked: Bool = false private var _isSelected: Bool = false + private var _isReadOnly: Bool = false public var isEnabled: Bool { get { return _isEnabled } @@ -69,6 +70,20 @@ import UIKit } } + public var isReadOnly: Bool { + get { return _isReadOnly } + set (readOnly) { + + _isEnabled = true + _isLocked = false + _isSelected = false + _showError = false + _isReadOnly = readOnly + + fieldState = readOnly ? .disabled : .original + } + } + public var showError: Bool { get { return _showError } set (error) {