From ebccc6bd28b01476b0d8d04b1bfc4282cebc3f31 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 14 Nov 2019 14:59:39 -0500 Subject: [PATCH] The latest state of entry. --- MVMCoreUI/Atoms/TextFields/DigitBox.swift | 9 +++-- .../Atoms/TextFields/DigitEntryField.swift | 2 +- .../Atoms/TextFields/DropdownEntryField.swift | 2 -- MVMCoreUI/Atoms/TextFields/EntryField.swift | 12 ++++--- .../TextFields/ItemDropdownEntryField.swift | 1 + .../Atoms/TextFields/MdnEntryField.swift | 28 +++++++++------- .../Atoms/TextFields/TextEntryField.swift | 33 +++++++++---------- MVMCoreUI/Containers/views/FormView.swift | 14 ++++---- .../FormValidator+TextFields.swift | 2 +- 9 files changed, 56 insertions(+), 47 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/DigitBox.swift b/MVMCoreUI/Atoms/TextFields/DigitBox.swift index 95135f69..1c1776d8 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitBox.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitBox.swift @@ -18,7 +18,12 @@ import UIKit // MARK: - Outlets //-------------------------------------------------- - let digitField = UITextField(frame: .zero) + let digitField: UITextField = { + let textField = UITextField(frame: .zero) + textField.textAlignment = .center + textField.keyboardType = .numberPad + return textField + }() //-------------------------------------------------- // MARK: - Properties @@ -68,8 +73,6 @@ import UIKit translatesAutoresizingMaskIntoConstraints = false backgroundColor = .white digitField.delegate = self - digitField.textAlignment = .center - digitField.keyboardType = .numberPad showErrorState(false) widthConstraint = widthAnchor.constraint(equalToConstant: 39) diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift index fe8340e0..f8a2ccbf 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift @@ -115,7 +115,7 @@ import UIKit self.numberOfDigits = numberOfDigits } - public init(numberOfDigits: Int, bothDelegates delegate: (UITextFieldDelegate & TextFieldDelegate)?, size: CGFloat? = nil) { + public init(numberOfDigits: Int, bothDelegates delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?, size: CGFloat? = nil) { self.numberOfDigits = numberOfDigits super.init(bothDelegates: delegate) } diff --git a/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift index c36834c5..2bb89424 100644 --- a/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift @@ -24,8 +24,6 @@ import UIKit return caret }() - - //-------------------------------------------------- // MARK: - Property Observers //-------------------------------------------------- diff --git a/MVMCoreUI/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atoms/TextFields/EntryField.swift index 63c506cc..d72d4be7 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryField.swift @@ -9,7 +9,6 @@ import UIKit /** - * This class is intended to be subclassed by a class that will add views subclassed under UIControl. * The EntryForm provides the base logic for the description label, placeholder/error label and field container. * * When subclassing, be sure to override setupFieldContainerContent(). In this method you will setup all the content bound to the field container. @@ -74,7 +73,7 @@ import UIKit } } - /// Toggles original or disabled UI. + /// Toggles enabled (original) or disabled UI. public var isEnabled = true { didSet { DispatchQueue.main.async { [weak self] in @@ -82,13 +81,13 @@ import UIKit self.isUserInteractionEnabled = self.isEnabled self.entryContainer.isEnabled = self.isEnabled - self.feedback = self.showError ? self.errorMessage : nil + self.feedbackLabel.textColor = self.isEnabled ? .black : .mfSilver() self.titleLabel.textColor = self.isEnabled ? .mfBattleshipGrey() : .mfSilver() } } } - // Toggles original or locked UI. + /// Toggles original or locked UI. public var isLocked = false { didSet { DispatchQueue.main.async { [weak self] in @@ -100,6 +99,7 @@ import UIKit } } + /// Toggles selected or original (unselected) UI. public var isSelected = false { didSet { DispatchQueue.main.async { [weak self] in @@ -110,6 +110,10 @@ import UIKit } } + //-------------------------------------------------- + // MARK: - Computed Properties for Outlets + //-------------------------------------------------- + /// Sets the text of titleLabel public var title: String? { get { return titleLabel.text } diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift index 44982d4d..41efd185 100644 --- a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift @@ -8,6 +8,7 @@ import UIKit + class ItemDropdownEntryField: DropdownEntryField { //-------------------------------------------------- // MARK: - Properties diff --git a/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift index a9c76e83..26a5266f 100644 --- a/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift @@ -11,7 +11,9 @@ import ContactsUI import UIKit import MVMCore - +/** + This class provides the convenience of formatting the MDN entered/displayer for the user. + */ @objcMembers open class MdnEntryField: TextEntryField, ABPeoplePickerNavigationControllerDelegate, CNContactPickerDelegate { //-------------------------------------------------- // MARK: - Properties @@ -20,12 +22,18 @@ import MVMCore public var isNationalMDN = true public var shouldValidateMDN = false + //-------------------------------------------------- + // MARK: - Delegate + //-------------------------------------------------- + + /// Holds a reference to the delegating class so this class can internally influence the TextField behavior as well. private weak var outsiderTextDelegate: UITextFieldDelegate? //-------------------------------------------------- // MARK: - Property Observers //-------------------------------------------------- + /// Formats the MDN when setting and removes format of MDN when reading. public var mdn: String? { get { return MVMCoreUIUtility.removeMdnFormat(text) } set { text = MVMCoreUIUtility.formatMdn(newValue) } @@ -35,11 +43,8 @@ import MVMCore public override weak var uiTextFieldDelegate: UITextFieldDelegate? { get { return textField.delegate } set { - textField.delegate = newValue + textField.delegate = self outsiderTextDelegate = newValue - if newValue != nil { - textField.delegate = self - } } } @@ -56,10 +61,10 @@ import MVMCore } /// - parameter bothDelegates: Sets both MF/UI Text Field Delegates. - public override init(bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) { - super.init(frame: .zero) - setBothTextDelegates(to: bothDelegates) - } + public override init(bothDelegates: (UITextFieldDelegate & ObservingTextFieldDelegate)?) { + super.init(frame: .zero) + setBothTextDelegates(to: bothDelegates) + } required public init?(coder: NSCoder) { super.init(coder: coder) @@ -78,7 +83,7 @@ import MVMCore let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar() let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts(_:))) - let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissTextFieldResponder(_:))) + let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissField(_:))) toolbar.items = [contacts, space, dismissButton] textField.inputAccessoryView = toolbar } @@ -143,7 +148,8 @@ import MVMCore unformedMDN.count == 11, unformedMDN[(unformedMDN.index(unformedMDN.startIndex, offsetBy: 0))] == "1" { - unformattedMDN = (unformedMDN as NSString).substring(from: 1) + let startIndex = unformedMDN.index(unformedMDN.startIndex, offsetBy: 1) + unformattedMDN = String(unformedMDN[startIndex...]) } text = unformattedMDN diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index ae2ff63f..8d4aa4aa 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -9,7 +9,7 @@ import UIKit -@objc public protocol TextFieldDelegate: NSObjectProtocol { +@objc public protocol ObservingTextFieldDelegate: NSObjectProtocol { /// Called when the entered text becomes valid based on the validation block @objc optional func isValid(textfield: TextEntryField?) /// Called when the entered text becomes invalid based on the validation block @@ -69,6 +69,7 @@ import UIKit } } + /// Placeholder access for the TextField. public var placeholder: String? { get { return textField.placeholder } set { textField.placeholder = newValue } @@ -89,15 +90,15 @@ import UIKit //-------------------------------------------------- /// The delegate and block for validation. Validates if the text that the user has entered is valid or not. Checked after each change if there is a delegate. - public weak var mfTextFieldDelegate: TextFieldDelegate? { + public weak var observingTextFieldDelegate: ObservingTextFieldDelegate? { didSet { - if mfTextFieldDelegate != nil && !observingForChange { + if observingTextFieldDelegate != nil && !observingForChange { observingForChange = true NotificationCenter.default.addObserver(self, selector: #selector(valueChanged), name: UITextField.textDidChangeNotification, object: textField) NotificationCenter.default.addObserver(self, selector: #selector(endInputing), name: UITextField.textDidEndEditingNotification, object: textField) NotificationCenter.default.addObserver(self, selector: #selector(startEditing), name: UITextField.textDidBeginEditingNotification, object: textField) - } else if mfTextFieldDelegate == nil && observingForChange { + } else if observingTextFieldDelegate == nil && observingForChange { observingForChange = false NotificationCenter.default.removeObserver(self, name: UITextField.textDidChangeNotification, object: textField) NotificationCenter.default.removeObserver(self, name: UITextField.textDidEndEditingNotification, object: textField) @@ -131,7 +132,7 @@ import UIKit } /// - parameter bothDelegates: Sets both MF/UI Text Field Delegates. - public init(bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) { + public init(bothDelegates: (UITextFieldDelegate & ObservingTextFieldDelegate)?) { super.init(frame: .zero) setBothTextDelegates(to: bothDelegates) } @@ -180,12 +181,13 @@ import UIKit open func clearErrorState() { textField.accessibilityValue = nil + feedback = nil entryContainer.originalUI() } - public func setBothTextDelegates(to delegate: (UITextFieldDelegate & TextFieldDelegate)?) { + public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) { - mfTextFieldDelegate = delegate + observingTextFieldDelegate = delegate uiTextFieldDelegate = delegate } @@ -199,17 +201,16 @@ import UIKit override open func resignFirstResponder() -> Bool { textField.resignFirstResponder() - return true } - @objc func dismissTextFieldResponder(_ sender: Any?) { + @objc func dismissField(_ sender: Any?) { - _ = textField.resignFirstResponder() + _ = self.resignFirstResponder() } //-------------------------------------------------- - // MARK: - Observing for change + // MARK: - Observing for Change (TextFieldDelegate) //-------------------------------------------------- @objc func valueChanged() { @@ -225,11 +226,11 @@ import UIKit if previousValidity && !isValid { feedback = errorMessage - mfTextFieldDelegate?.isInvalid?(textfield: self) + observingTextFieldDelegate?.isInvalid?(textfield: self) } else if !previousValidity && isValid { clearErrorState() - mfTextFieldDelegate?.isValid?(textfield: self) + observingTextFieldDelegate?.isValid?(textfield: self) } } @@ -258,8 +259,7 @@ extension TextEntryField { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) guard let delegateObject = delegateObject, - let dictionary = json, - !dictionary.isEmpty + let dictionary = json else { return } FormValidator.setupValidation(molecule: self, delegate: delegateObject.formValidationProtocol) @@ -306,11 +306,10 @@ extension TextEntryField { } if let formValidationProtocol = delegateObject.formValidationProtocol { - mfTextFieldDelegate = FormValidator.getFormValidatorFor(delegate: formValidationProtocol) + observingTextFieldDelegate = FormValidator.getFormValidatorFor(delegate: formValidationProtocol) as? ObservingTextFieldDelegate } uiTextFieldDelegate = delegateObject.uiTextFieldDelegate - MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) } } diff --git a/MVMCoreUI/Containers/views/FormView.swift b/MVMCoreUI/Containers/views/FormView.swift index a89f2c8f..201bfb3d 100644 --- a/MVMCoreUI/Containers/views/FormView.swift +++ b/MVMCoreUI/Containers/views/FormView.swift @@ -14,6 +14,7 @@ import UIKit // MARK: - Drawing Properties //-------------------------------------------------- + /// The bottom border line. public var bottomBar: CAShapeLayer = { let layer = CAShapeLayer() layer.backgroundColor = UIColor.black.cgColor @@ -62,7 +63,7 @@ import UIKit /// Holds reference to delegateObject to inform molecular tableView of an update. weak var delegateObject: MVMCoreUIDelegateObject? - + //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- @@ -79,6 +80,7 @@ import UIKit refreshUI() } + /// This handles the top, left, and right border lines. open override func draw(_ rect: CGRect) { super.draw(rect) @@ -111,14 +113,13 @@ import UIKit //-------------------------------------------------- // MARK: - Draw States //-------------------------------------------------- - + open func originalUI() { isUserInteractionEnabled = true hideBorder = false borderStrokeColor = .mfSilver() bottomBar.backgroundColor = UIColor.black.cgColor - refreshUI(bottomBarSize: 1) } @@ -128,7 +129,6 @@ import UIKit hideBorder = false borderStrokeColor = .mfPumpkin() bottomBar.backgroundColor = UIColor.mfPumpkin().cgColor - refreshUI(bottomBarSize: 4) } @@ -138,7 +138,6 @@ import UIKit hideBorder = false borderStrokeColor = .black bottomBar.backgroundColor = UIColor.black.cgColor - refreshUI(bottomBarSize: 1) } @@ -146,8 +145,8 @@ import UIKit isUserInteractionEnabled = false hideBorder = true + borderStrokeColor = .clear bottomBar.backgroundColor = UIColor.clear.cgColor - refreshUI(bottomBarSize: 1) } @@ -156,8 +155,7 @@ import UIKit isUserInteractionEnabled = false borderStrokeColor = .mfSilver() hideBorder = false - bottomBar.backgroundColor = self.isEnabled ? UIColor.black.cgColor : UIColor.mfSilver().cgColor - + bottomBar.backgroundColor = UIColor.mfSilver().cgColor refreshUI(bottomBarSize: 1) } diff --git a/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift b/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift index e8d79245..21599abf 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift @@ -39,7 +39,7 @@ import Foundation } // Temporary: Looking to either combine or separate entirely with MFTextFieldDelegate. -extension FormValidator: TextFieldDelegate { +extension FormValidator: ObservingTextFieldDelegate { public func dismissField(_ sender: Any?) {