mvm_core_ui/MVMCoreUI/BaseClasses/TextView.swift
Kevin G Christiano 4fb8e05498 now
2020-04-09 15:44:45 -04:00

246 lines
8.0 KiB
Swift

//
// TextView.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 4/1/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import UIKit
@objc open class TextView: UITextView, UITextViewDelegate {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
open var model: MoleculeModelProtocol?
private var initialSetupPerformed = false
/// Set this property if you want updateView to update the font based on this standard and the size passed in.
public var standardFontSize: CGFloat = 0.0
public var isShowingPlaceholder = true
/// Set to true to hide the blinking textField cursor.
public var hideBlinkingCaret = false
private var textTraits: (color: UIColor, font: UIFont) = (color: .mvmBlack,
font: Styler.Font.RegularBodySmall.getFont())
private var placeholderTraits: (text: String, color: UIColor, font: UIFont) = (text: "",
color: .mvmCoolGray3, font: Styler.Font.RegularMicro.getFont())
//--------------------------------------------------
// MARK: - Delegate
//--------------------------------------------------
/// Holds a reference to the delegating class so this class can internally influence the TextField behavior as well.
public weak var didDeleteDelegate: TextFieldDidDeleteProtocol?
/// Holds a reference to the delegating class so this class can internally influence the TextField behavior as well.
private weak var proprietorTextDelegate: UITextViewDelegate?
/// If you're using a ViewController, you must set this to it
public weak var uiTextViewDelegate: UITextViewDelegate? {
get { return delegate }
set {
delegate = self
proprietorTextDelegate = newValue
}
}
//--------------------------------------------------
// MARK: - Constraint
//--------------------------------------------------
public var heightConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Initialization
//--------------------------------------------------
public override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: .zero, textContainer: nil)
initialSetup()
}
public convenience init() {
self.init(frame: .zero, textContainer: nil)
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
initialSetup()
}
convenience init(placeholderText: String, delegate: UITextViewDelegate?) {
self.init(frame: .zero, textContainer: nil)
self.delegate = delegate
self.placeholderTraits.text = placeholderText
}
public func initialSetup() {
if !initialSetupPerformed {
tintColor = .mvmBlack
initialSetupPerformed = true
setupView()
}
}
open override func caretRect(for position: UITextPosition) -> CGRect {
if hideBlinkingCaret {
return .zero
}
let caretRect = super.caretRect(for: position)
return CGRect(origin: caretRect.origin, size: CGSize(width: 1, height: caretRect.height))
}
open override func deleteBackward() {
super.deleteBackward()
didDeleteDelegate?.textFieldDidDelete()
}
open func setTextViewState() {
if isShowingPlaceholder {
text = ""
font = textTraits.font
textColor = textTraits.color
isShowingPlaceholder = false
} else if text.isEmpty {
isShowingPlaceholder = true
textColor = placeholderTraits.color
text = placeholderTraits.text
font = placeholderTraits.font
}
}
//--------------------------------------------------
// MARK: - UITextViewDelegate
//--------------------------------------------------
//#pragma Mark UITextView Delegate methods forwarding
@objc public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
return proprietorTextDelegate?.textViewShouldBeginEditing?(textView) ?? true
}
@objc public func textViewDidBeginEditing(_ textView: UITextView) {
proprietorTextDelegate?.textViewDidBeginEditing?(textView)
}
@objc public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
return proprietorTextDelegate?.textView?(textView, shouldChangeTextIn: range, replacementText: text) ?? true
}
@objc public func textViewDidChange(_ textView: UITextView) {
setTextViewState()
proprietorTextDelegate?.textViewDidChange?(textView)
}
@objc public func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
return proprietorTextDelegate?.textViewShouldEndEditing?(textView) ?? true
}
@objc public func textViewDidEndEditing(_ textView: UITextView) {
proprietorTextDelegate?.textViewDidEndEditing?(textView)
}
}
/// MARK:- MVMCoreViewProtocol
extension TextView: MVMCoreViewProtocol {
open func updateView(_ size: CGFloat) { }
/// Will be called only once.
open func setupView() {
translatesAutoresizingMaskIntoConstraints = false
insetsLayoutMarginsFromSafeArea = false
showsVerticalScrollIndicator = false
showsHorizontalScrollIndicator = false
backgroundColor = .clear
clipsToBounds = true
smartQuotesType = .no
smartDashesType = .no
smartInsertDeleteType = .no
font = textTraits.font
layer.borderWidth = 1
layer.borderColor = UIColor.mvmBlack.cgColor
isEditable = true
}
}
/// MARK:- MoleculeViewProtocol
extension TextView: MoleculeViewProtocol {
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.model = model
if let color = model.backgroundColor?.uiColor {
backgroundColor = color
}
guard let model = model as? TextViewModel else { return }
if let height = model.height {
heightConstraint = heightAnchor.constraint(equalToConstant: height)
heightConstraint?.isActive = true
}
isEditable = model.isEditable
textAlignment = model.textAlignment
textColor = model.textColor.uiColor
layer.borderColor = model.borderColor?.cgColor
layer.borderWidth = model.borderWidth
text = model.text
isShowingPlaceholder = model.text.isEmpty
placeholderTraits.font = model.placeholderFont.getFont()
placeholderTraits.text = model.placeholder
uiTextViewDelegate = delegateObject?.uiTextViewDelegate
if let accessibilityText = model.accessibilityText {
accessibilityLabel = accessibilityText
}
font = model.fontStyle.getFont()
standardFontSize = model.fontStyle.pointSize()
if let font = font {
textTraits.font = font
}
let fontSize = model.fontSize
if let fontSize = fontSize {
standardFontSize = fontSize
}
if let fontName = model.fontName {
font = Styler.Font(rawValue: fontName)?.getFont()
textTraits.font = font!
} else if let fontSize = fontSize {
font = font?.updateSize(fontSize)
textTraits.font = font!
}
if isEditable {
MVMCoreUICommonViewsUtility.addDismissToolbar(to: self, delegate: delegateObject?.uiTextViewDelegate)
}
}
open func reset() {
setNeedsDisplay()
backgroundColor = .clear
text = ""
}
}