The latest state of entry.

This commit is contained in:
Kevin G Christiano 2019-11-14 14:59:39 -05:00
parent 80c700ba55
commit ebccc6bd28
9 changed files with 56 additions and 47 deletions

View File

@ -18,7 +18,12 @@ import UIKit
// MARK: - Outlets // 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 // MARK: - Properties
@ -68,8 +73,6 @@ import UIKit
translatesAutoresizingMaskIntoConstraints = false translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .white backgroundColor = .white
digitField.delegate = self digitField.delegate = self
digitField.textAlignment = .center
digitField.keyboardType = .numberPad
showErrorState(false) showErrorState(false)
widthConstraint = widthAnchor.constraint(equalToConstant: 39) widthConstraint = widthAnchor.constraint(equalToConstant: 39)

View File

@ -115,7 +115,7 @@ import UIKit
self.numberOfDigits = numberOfDigits 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 self.numberOfDigits = numberOfDigits
super.init(bothDelegates: delegate) super.init(bothDelegates: delegate)
} }

View File

@ -24,8 +24,6 @@ import UIKit
return caret return caret
}() }()
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Property Observers // MARK: - Property Observers
//-------------------------------------------------- //--------------------------------------------------

View File

@ -9,7 +9,6 @@
import UIKit 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. * 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. * 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 { public var isEnabled = true {
didSet { didSet {
DispatchQueue.main.async { [weak self] in DispatchQueue.main.async { [weak self] in
@ -82,13 +81,13 @@ import UIKit
self.isUserInteractionEnabled = self.isEnabled self.isUserInteractionEnabled = self.isEnabled
self.entryContainer.isEnabled = 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() self.titleLabel.textColor = self.isEnabled ? .mfBattleshipGrey() : .mfSilver()
} }
} }
} }
// Toggles original or locked UI. /// Toggles original or locked UI.
public var isLocked = false { public var isLocked = false {
didSet { didSet {
DispatchQueue.main.async { [weak self] in DispatchQueue.main.async { [weak self] in
@ -100,6 +99,7 @@ import UIKit
} }
} }
/// Toggles selected or original (unselected) UI.
public var isSelected = false { public var isSelected = false {
didSet { didSet {
DispatchQueue.main.async { [weak self] in DispatchQueue.main.async { [weak self] in
@ -110,6 +110,10 @@ import UIKit
} }
} }
//--------------------------------------------------
// MARK: - Computed Properties for Outlets
//--------------------------------------------------
/// Sets the text of titleLabel /// Sets the text of titleLabel
public var title: String? { public var title: String? {
get { return titleLabel.text } get { return titleLabel.text }

View File

@ -8,6 +8,7 @@
import UIKit import UIKit
class ItemDropdownEntryField: DropdownEntryField { class ItemDropdownEntryField: DropdownEntryField {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties

View File

@ -11,7 +11,9 @@ import ContactsUI
import UIKit import UIKit
import MVMCore import MVMCore
/**
This class provides the convenience of formatting the MDN entered/displayer for the user.
*/
@objcMembers open class MdnEntryField: TextEntryField, ABPeoplePickerNavigationControllerDelegate, CNContactPickerDelegate { @objcMembers open class MdnEntryField: TextEntryField, ABPeoplePickerNavigationControllerDelegate, CNContactPickerDelegate {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
@ -20,12 +22,18 @@ import MVMCore
public var isNationalMDN = true public var isNationalMDN = true
public var shouldValidateMDN = false 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? private weak var outsiderTextDelegate: UITextFieldDelegate?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Property Observers // MARK: - Property Observers
//-------------------------------------------------- //--------------------------------------------------
/// Formats the MDN when setting and removes format of MDN when reading.
public var mdn: String? { public var mdn: String? {
get { return MVMCoreUIUtility.removeMdnFormat(text) } get { return MVMCoreUIUtility.removeMdnFormat(text) }
set { text = MVMCoreUIUtility.formatMdn(newValue) } set { text = MVMCoreUIUtility.formatMdn(newValue) }
@ -35,11 +43,8 @@ import MVMCore
public override weak var uiTextFieldDelegate: UITextFieldDelegate? { public override weak var uiTextFieldDelegate: UITextFieldDelegate? {
get { return textField.delegate } get { return textField.delegate }
set { set {
textField.delegate = newValue textField.delegate = self
outsiderTextDelegate = newValue outsiderTextDelegate = newValue
if newValue != nil {
textField.delegate = self
}
} }
} }
@ -56,10 +61,10 @@ import MVMCore
} }
/// - parameter bothDelegates: Sets both MF/UI Text Field Delegates. /// - parameter bothDelegates: Sets both MF/UI Text Field Delegates.
public override init(bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) { public override init(bothDelegates: (UITextFieldDelegate & ObservingTextFieldDelegate)?) {
super.init(frame: .zero) super.init(frame: .zero)
setBothTextDelegates(to: bothDelegates) setBothTextDelegates(to: bothDelegates)
} }
required public init?(coder: NSCoder) { required public init?(coder: NSCoder) {
super.init(coder: coder) super.init(coder: coder)
@ -78,7 +83,7 @@ import MVMCore
let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar() let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar()
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) 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 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] toolbar.items = [contacts, space, dismissButton]
textField.inputAccessoryView = toolbar textField.inputAccessoryView = toolbar
} }
@ -143,7 +148,8 @@ import MVMCore
unformedMDN.count == 11, unformedMDN.count == 11,
unformedMDN[(unformedMDN.index(unformedMDN.startIndex, offsetBy: 0))] == "1" { 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 text = unformattedMDN

View File

@ -9,7 +9,7 @@
import UIKit import UIKit
@objc public protocol TextFieldDelegate: NSObjectProtocol { @objc public protocol ObservingTextFieldDelegate: NSObjectProtocol {
/// Called when the entered text becomes valid based on the validation block /// Called when the entered text becomes valid based on the validation block
@objc optional func isValid(textfield: TextEntryField?) @objc optional func isValid(textfield: TextEntryField?)
/// Called when the entered text becomes invalid based on the validation block /// 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? { public var placeholder: String? {
get { return textField.placeholder } get { return textField.placeholder }
set { textField.placeholder = newValue } 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. /// 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 { didSet {
if mfTextFieldDelegate != nil && !observingForChange { if observingTextFieldDelegate != nil && !observingForChange {
observingForChange = true observingForChange = true
NotificationCenter.default.addObserver(self, selector: #selector(valueChanged), name: UITextField.textDidChangeNotification, object: textField) 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(endInputing), name: UITextField.textDidEndEditingNotification, object: textField)
NotificationCenter.default.addObserver(self, selector: #selector(startEditing), name: UITextField.textDidBeginEditingNotification, 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 observingForChange = false
NotificationCenter.default.removeObserver(self, name: UITextField.textDidChangeNotification, object: textField) NotificationCenter.default.removeObserver(self, name: UITextField.textDidChangeNotification, object: textField)
NotificationCenter.default.removeObserver(self, name: UITextField.textDidEndEditingNotification, 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. /// - parameter bothDelegates: Sets both MF/UI Text Field Delegates.
public init(bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) { public init(bothDelegates: (UITextFieldDelegate & ObservingTextFieldDelegate)?) {
super.init(frame: .zero) super.init(frame: .zero)
setBothTextDelegates(to: bothDelegates) setBothTextDelegates(to: bothDelegates)
} }
@ -180,12 +181,13 @@ import UIKit
open func clearErrorState() { open func clearErrorState() {
textField.accessibilityValue = nil textField.accessibilityValue = nil
feedback = nil
entryContainer.originalUI() entryContainer.originalUI()
} }
public func setBothTextDelegates(to delegate: (UITextFieldDelegate & TextFieldDelegate)?) { public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) {
mfTextFieldDelegate = delegate observingTextFieldDelegate = delegate
uiTextFieldDelegate = delegate uiTextFieldDelegate = delegate
} }
@ -199,17 +201,16 @@ import UIKit
override open func resignFirstResponder() -> Bool { override open func resignFirstResponder() -> Bool {
textField.resignFirstResponder() textField.resignFirstResponder()
return true 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() { @objc func valueChanged() {
@ -225,11 +226,11 @@ import UIKit
if previousValidity && !isValid { if previousValidity && !isValid {
feedback = errorMessage feedback = errorMessage
mfTextFieldDelegate?.isInvalid?(textfield: self) observingTextFieldDelegate?.isInvalid?(textfield: self)
} else if !previousValidity && isValid { } else if !previousValidity && isValid {
clearErrorState() clearErrorState()
mfTextFieldDelegate?.isValid?(textfield: self) observingTextFieldDelegate?.isValid?(textfield: self)
} }
} }
@ -258,8 +259,7 @@ extension TextEntryField {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
guard let delegateObject = delegateObject, guard let delegateObject = delegateObject,
let dictionary = json, let dictionary = json
!dictionary.isEmpty
else { return } else { return }
FormValidator.setupValidation(molecule: self, delegate: delegateObject.formValidationProtocol) FormValidator.setupValidation(molecule: self, delegate: delegateObject.formValidationProtocol)
@ -306,11 +306,10 @@ extension TextEntryField {
} }
if let formValidationProtocol = delegateObject.formValidationProtocol { if let formValidationProtocol = delegateObject.formValidationProtocol {
mfTextFieldDelegate = FormValidator.getFormValidatorFor(delegate: formValidationProtocol) observingTextFieldDelegate = FormValidator.getFormValidatorFor(delegate: formValidationProtocol) as? ObservingTextFieldDelegate
} }
uiTextFieldDelegate = delegateObject.uiTextFieldDelegate uiTextFieldDelegate = delegateObject.uiTextFieldDelegate
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate)
} }
} }

View File

@ -14,6 +14,7 @@ import UIKit
// MARK: - Drawing Properties // MARK: - Drawing Properties
//-------------------------------------------------- //--------------------------------------------------
/// The bottom border line.
public var bottomBar: CAShapeLayer = { public var bottomBar: CAShapeLayer = {
let layer = CAShapeLayer() let layer = CAShapeLayer()
layer.backgroundColor = UIColor.black.cgColor layer.backgroundColor = UIColor.black.cgColor
@ -62,7 +63,7 @@ import UIKit
/// Holds reference to delegateObject to inform molecular tableView of an update. /// Holds reference to delegateObject to inform molecular tableView of an update.
weak var delegateObject: MVMCoreUIDelegateObject? weak var delegateObject: MVMCoreUIDelegateObject?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Lifecycle // MARK: - Lifecycle
//-------------------------------------------------- //--------------------------------------------------
@ -79,6 +80,7 @@ import UIKit
refreshUI() refreshUI()
} }
/// This handles the top, left, and right border lines.
open override func draw(_ rect: CGRect) { open override func draw(_ rect: CGRect) {
super.draw(rect) super.draw(rect)
@ -111,14 +113,13 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Draw States // MARK: - Draw States
//-------------------------------------------------- //--------------------------------------------------
open func originalUI() { open func originalUI() {
isUserInteractionEnabled = true isUserInteractionEnabled = true
hideBorder = false hideBorder = false
borderStrokeColor = .mfSilver() borderStrokeColor = .mfSilver()
bottomBar.backgroundColor = UIColor.black.cgColor bottomBar.backgroundColor = UIColor.black.cgColor
refreshUI(bottomBarSize: 1) refreshUI(bottomBarSize: 1)
} }
@ -128,7 +129,6 @@ import UIKit
hideBorder = false hideBorder = false
borderStrokeColor = .mfPumpkin() borderStrokeColor = .mfPumpkin()
bottomBar.backgroundColor = UIColor.mfPumpkin().cgColor bottomBar.backgroundColor = UIColor.mfPumpkin().cgColor
refreshUI(bottomBarSize: 4) refreshUI(bottomBarSize: 4)
} }
@ -138,7 +138,6 @@ import UIKit
hideBorder = false hideBorder = false
borderStrokeColor = .black borderStrokeColor = .black
bottomBar.backgroundColor = UIColor.black.cgColor bottomBar.backgroundColor = UIColor.black.cgColor
refreshUI(bottomBarSize: 1) refreshUI(bottomBarSize: 1)
} }
@ -146,8 +145,8 @@ import UIKit
isUserInteractionEnabled = false isUserInteractionEnabled = false
hideBorder = true hideBorder = true
borderStrokeColor = .clear
bottomBar.backgroundColor = UIColor.clear.cgColor bottomBar.backgroundColor = UIColor.clear.cgColor
refreshUI(bottomBarSize: 1) refreshUI(bottomBarSize: 1)
} }
@ -156,8 +155,7 @@ import UIKit
isUserInteractionEnabled = false isUserInteractionEnabled = false
borderStrokeColor = .mfSilver() borderStrokeColor = .mfSilver()
hideBorder = false hideBorder = false
bottomBar.backgroundColor = self.isEnabled ? UIColor.black.cgColor : UIColor.mfSilver().cgColor bottomBar.backgroundColor = UIColor.mfSilver().cgColor
refreshUI(bottomBarSize: 1) refreshUI(bottomBarSize: 1)
} }

View File

@ -39,7 +39,7 @@ import Foundation
} }
// Temporary: Looking to either combine or separate entirely with MFTextFieldDelegate. // Temporary: Looking to either combine or separate entirely with MFTextFieldDelegate.
extension FormValidator: TextFieldDelegate { extension FormValidator: ObservingTextFieldDelegate {
public func dismissField(_ sender: Any?) { public func dismissField(_ sender: Any?) {