functioning border
This commit is contained in:
parent
077d94edd1
commit
2a251649af
@ -51,7 +51,7 @@ public protocol TextInputDidDeleteProtocol: class {
|
||||
public func initialSetup() {
|
||||
|
||||
if !initialSetupPerformed {
|
||||
tintColor = .black
|
||||
tintColor = .mvmBlack
|
||||
initialSetupPerformed = true
|
||||
setupView()
|
||||
}
|
||||
@ -87,7 +87,9 @@ extension TextField: MVMCoreViewProtocol {
|
||||
|
||||
/// MARK:- MoleculeViewProtocol
|
||||
extension TextField: MoleculeViewProtocol {
|
||||
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
|
||||
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
|
||||
if let color = model.backgroundColor?.uiColor {
|
||||
backgroundColor = color
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
|
||||
|
||||
@objc open class TextView: UITextView, UITextViewDelegate {
|
||||
@objc open class TextView: UITextView, UITextViewDelegate, MVMCoreViewProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -28,6 +28,98 @@ import UIKit
|
||||
return model as? TextViewModel
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Drawing Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
/// Total control over the drawn top, bottom, left and right borders.
|
||||
public var disableAllBorders = false
|
||||
|
||||
private(set) var fieldState: FieldState = .original {
|
||||
didSet (oldState) {
|
||||
// Will not update if new state is the same as old.
|
||||
if fieldState != oldState {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.fieldState.setStateUI(for: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines if the top, left, and right borders should be drawn.
|
||||
private var hideBorders = false
|
||||
|
||||
public var borderStrokeColor: UIColor = .mvmCoolGray3
|
||||
public var bottomStrokeColor: UIColor = .mvmBlack
|
||||
private var borderPath: UIBezierPath = UIBezierPath()
|
||||
private var bottomPath: UIBezierPath = UIBezierPath()
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Property Observers
|
||||
//--------------------------------------------------
|
||||
|
||||
private var _isEnabled: Bool = true
|
||||
private var _showError: Bool = false
|
||||
private var _isLocked: Bool = false
|
||||
private var _isSelected: Bool = false
|
||||
|
||||
public var isEnabled: Bool {
|
||||
get { return _isEnabled }
|
||||
set (enabled) {
|
||||
|
||||
_isEnabled = enabled
|
||||
_isLocked = false
|
||||
_isSelected = false
|
||||
_showError = false
|
||||
|
||||
fieldState = enabled ? .original : .disabled
|
||||
}
|
||||
}
|
||||
|
||||
public var showError: Bool {
|
||||
get { return _showError }
|
||||
set (error) {
|
||||
|
||||
_showError = error
|
||||
_isEnabled = true
|
||||
_isLocked = false
|
||||
_isSelected = false
|
||||
|
||||
fieldState = error ? .error : .original
|
||||
}
|
||||
}
|
||||
|
||||
public var isLocked: Bool {
|
||||
get { return _isLocked }
|
||||
set (locked) {
|
||||
|
||||
_isLocked = locked
|
||||
_isEnabled = true
|
||||
_isSelected = false
|
||||
_showError = false
|
||||
|
||||
fieldState = locked ? .locked : .original
|
||||
}
|
||||
}
|
||||
|
||||
public var isSelected: Bool {
|
||||
get { return _isSelected }
|
||||
set (selected) {
|
||||
|
||||
_isSelected = selected
|
||||
_isLocked = false
|
||||
_isEnabled = true
|
||||
|
||||
if _showError {
|
||||
fieldState = selected ? .selectedError : .error
|
||||
} else {
|
||||
fieldState = selected ? .selected : .original
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate
|
||||
//--------------------------------------------------
|
||||
@ -47,6 +139,8 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraint
|
||||
//--------------------------------------------------
|
||||
@ -77,7 +171,7 @@ import UIKit
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Setup
|
||||
// MARK: - Lifecycle
|
||||
//--------------------------------------------------
|
||||
|
||||
public func initialSetup() {
|
||||
@ -89,6 +183,187 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
open func updateView(_ size: CGFloat) {
|
||||
|
||||
refreshUI()
|
||||
}
|
||||
|
||||
/// Will be called only once.
|
||||
open func setupView() {
|
||||
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
insetsLayoutMarginsFromSafeArea = false
|
||||
showsVerticalScrollIndicator = false
|
||||
showsHorizontalScrollIndicator = false
|
||||
contentInset = UIEdgeInsets(top: Padding.Three, left: Padding.Three, bottom: Padding.Three, right: Padding.Three)
|
||||
backgroundColor = .mvmWhite
|
||||
clipsToBounds = true
|
||||
smartQuotesType = .no
|
||||
smartDashesType = .no
|
||||
smartInsertDeleteType = .no
|
||||
font = textViewModel?.fontStyle.getFont()
|
||||
isEditable = true
|
||||
isOpaque = false
|
||||
}
|
||||
|
||||
open func reset() {
|
||||
|
||||
backgroundColor = .mvmWhite
|
||||
text = ""
|
||||
inputAccessoryView?.removeFromSuperview()
|
||||
contentInset = UIEdgeInsets(top: Padding.Three, left: Padding.Three, bottom: Padding.Three, right: Padding.Three)
|
||||
}
|
||||
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
refreshUI(bottomBarSize: showError ? 4 : 1)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Draw
|
||||
//--------------------------------------------------
|
||||
|
||||
/// This handles the top, left, and right border lines.
|
||||
open override func draw(_ rect: CGRect) {
|
||||
super.draw(rect)
|
||||
|
||||
borderPath.removeAllPoints()
|
||||
bottomPath.removeAllPoints()
|
||||
|
||||
if !disableAllBorders && !hideBorders {
|
||||
// Brings the other half of the line inside the view to prevent cropping.
|
||||
let origin = bounds.origin
|
||||
let size = frame.size
|
||||
let insetLean: CGFloat = 0.5
|
||||
borderPath.lineWidth = 1
|
||||
|
||||
borderPath.move(to: CGPoint(x: origin.x + insetLean, y: origin.y + size.height))
|
||||
borderPath.addLine(to: CGPoint(x: origin.x + insetLean, y: origin.y + insetLean))
|
||||
borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + insetLean))
|
||||
borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + size.height))
|
||||
|
||||
borderStrokeColor.setStroke()
|
||||
borderPath.stroke()
|
||||
|
||||
bottomPath.lineWidth = 4
|
||||
bottomPath.move(to: CGPoint(x: origin.x + size.width, y: origin.y + size.height - 2))
|
||||
bottomPath.addLine(to: CGPoint(x: origin.x, y: origin.y + size.height - 2))
|
||||
|
||||
bottomStrokeColor.setStroke()
|
||||
bottomPath.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Draw States
|
||||
//--------------------------------------------------
|
||||
|
||||
public enum FieldState {
|
||||
case original
|
||||
case error
|
||||
case selectedError
|
||||
case selected
|
||||
case locked
|
||||
case disabled
|
||||
|
||||
public func setStateUI(for formField: TextView) {
|
||||
|
||||
switch self {
|
||||
case .original:
|
||||
formField.originalUI()
|
||||
|
||||
case .error:
|
||||
formField.errorUI()
|
||||
|
||||
case .selectedError:
|
||||
formField.selectedErrorUI()
|
||||
|
||||
case .selected:
|
||||
formField.selectedUI()
|
||||
|
||||
case .locked:
|
||||
formField.lockedUI()
|
||||
|
||||
case .disabled:
|
||||
formField.disabledUI()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open func originalUI() {
|
||||
|
||||
isEditable = true
|
||||
hideBorders = false
|
||||
borderStrokeColor = .mvmCoolGray3
|
||||
bottomStrokeColor = .mvmBlack
|
||||
refreshUI(bottomBarSize: 1)
|
||||
}
|
||||
|
||||
open func errorUI() {
|
||||
|
||||
isEditable = true
|
||||
hideBorders = false
|
||||
borderStrokeColor = .mvmOrange
|
||||
bottomStrokeColor = .mvmOrange
|
||||
refreshUI(bottomBarSize: 4)
|
||||
}
|
||||
|
||||
open func selectedErrorUI() {
|
||||
|
||||
isEditable = true
|
||||
hideBorders = false
|
||||
borderStrokeColor = .mvmBlack
|
||||
bottomStrokeColor = .mvmOrange
|
||||
refreshUI(bottomBarSize: 4)
|
||||
}
|
||||
|
||||
open func selectedUI() {
|
||||
|
||||
isEditable = true
|
||||
hideBorders = false
|
||||
borderStrokeColor = .mvmBlack
|
||||
bottomStrokeColor = .mvmBlack
|
||||
refreshUI(bottomBarSize: 1)
|
||||
}
|
||||
|
||||
open func lockedUI() {
|
||||
|
||||
isEditable = false
|
||||
hideBorders = true
|
||||
borderStrokeColor = .clear
|
||||
bottomStrokeColor = .clear
|
||||
refreshUI(bottomBarSize: 1)
|
||||
}
|
||||
|
||||
open func disabledUI() {
|
||||
|
||||
isEditable = false
|
||||
hideBorders = false
|
||||
borderStrokeColor = .mvmCoolGray3
|
||||
bottomStrokeColor = .mvmCoolGray3
|
||||
refreshUI(bottomBarSize: 1)
|
||||
}
|
||||
|
||||
open func refreshUI(bottomBarSize: CGFloat? = nil, updateMoleculeLayout: Bool = false) {
|
||||
|
||||
if !disableAllBorders {
|
||||
// let size: CGFloat = bottomBarSize ?? (showError ? 4 : 1)
|
||||
// var heightChanged = false
|
||||
|
||||
// if let bottomHeight = bottomBar?.bounds.height {
|
||||
// heightChanged = size != bottomHeight
|
||||
// }
|
||||
|
||||
if updateMoleculeLayout {//|| heightChanged {
|
||||
delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
|
||||
}
|
||||
|
||||
setNeedsDisplay()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
@ -177,36 +452,12 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
contentInset = UIEdgeInsets(top: Padding.Three, left: Padding.Three, bottom: Padding.Three, right: Padding.Three)
|
||||
backgroundColor = .mvmWhite
|
||||
clipsToBounds = true
|
||||
smartQuotesType = .no
|
||||
smartDashesType = .no
|
||||
smartInsertDeleteType = .no
|
||||
font = textViewModel?.fontStyle.getFont()
|
||||
layer.borderWidth = 1
|
||||
layer.borderColor = UIColor.mvmBlack.cgColor
|
||||
isEditable = true
|
||||
}
|
||||
}
|
||||
|
||||
/// MARK:- MoleculeViewProtocol
|
||||
// MARK:- MoleculeViewProtocol
|
||||
extension TextView: MoleculeViewProtocol {
|
||||
|
||||
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
self.model = model
|
||||
self.delegateObject = delegateObject
|
||||
|
||||
if let color = model.backgroundColor?.uiColor {
|
||||
backgroundColor = color
|
||||
@ -223,8 +474,6 @@ extension TextView: MoleculeViewProtocol {
|
||||
isEditable = model.isEditable
|
||||
textAlignment = model.textAlignment
|
||||
textColor = model.textColor.uiColor
|
||||
layer.borderColor = model.borderColor?.cgColor
|
||||
layer.borderWidth = model.borderWidth
|
||||
text = model.text
|
||||
uiTextViewDelegate = delegateObject?.uiTextViewDelegate
|
||||
isShowingPlaceholder = model.text!.isEmpty
|
||||
@ -237,17 +486,14 @@ extension TextView: MoleculeViewProtocol {
|
||||
setPlaceholderIfAvailable()
|
||||
|
||||
if isEditable {
|
||||
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
|
||||
MVMCoreUICommonViewsUtility.addDismissToolbar(to: self, delegate: delegateObject?.uiTextViewDelegate)
|
||||
|
||||
if model.selected ?? false {
|
||||
isSelected = true
|
||||
model.wasInitiallySelected = true
|
||||
becomeFirstResponder()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open func reset() {
|
||||
|
||||
backgroundColor = .mvmWhite
|
||||
text = ""
|
||||
inputAccessoryView?.removeFromSuperview()
|
||||
layer.borderColor = UIColor.mvmBlack.cgColor
|
||||
contentInset = UIEdgeInsets(top: Padding.Three, left: Padding.Three, bottom: Padding.Three, right: Padding.Three)
|
||||
layer.borderWidth = 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,8 +27,8 @@ open class TextViewModel: TextEntryFieldModel {
|
||||
public var placeholderFontStyle: Styler.Font = Styler.Font.RegularMicro
|
||||
public var showsPlaceholder: Bool = true
|
||||
public var isEditable: Bool = true
|
||||
public var borderColor: Color?
|
||||
public var borderWidth: CGFloat = 0
|
||||
// public var borderColor: Color?
|
||||
// public var borderWidth: CGFloat = 0
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
@ -44,12 +44,12 @@ open class TextViewModel: TextEntryFieldModel {
|
||||
case textAlignment
|
||||
case attributes
|
||||
case height
|
||||
case borderColor
|
||||
case borderWidth
|
||||
case placeholder
|
||||
// case borderColor
|
||||
// case borderWidth
|
||||
// case placeholder
|
||||
case placeholderFontStyle
|
||||
case isEditable = "editable"
|
||||
case hideBlinkingCaret
|
||||
// case hideBlinkingCaret
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -76,15 +76,15 @@ open class TextViewModel: TextEntryFieldModel {
|
||||
self.isEditable = isEditable
|
||||
}
|
||||
|
||||
if let borderWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .borderWidth) {
|
||||
self.borderWidth = borderWidth
|
||||
}
|
||||
// if let borderWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .borderWidth) {
|
||||
// self.borderWidth = borderWidth
|
||||
// }
|
||||
|
||||
if let fontStyle = try typeContainer.decodeIfPresent(Styler.Font.self, forKey: .fontStyle) {
|
||||
self.fontStyle = fontStyle
|
||||
}
|
||||
|
||||
borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor)
|
||||
// borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor)
|
||||
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
|
||||
height = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .height)
|
||||
}
|
||||
@ -95,13 +95,13 @@ open class TextViewModel: TextEntryFieldModel {
|
||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||
try container.encodeIfPresent(textColor, forKey: .textColor)
|
||||
try container.encodeIfPresent(fontStyle, forKey: .fontStyle)
|
||||
try container.encodeIfPresent(borderColor, forKey: .borderColor)
|
||||
// try container.encodeIfPresent(borderColor, forKey: .borderColor)
|
||||
try container.encodeIfPresent(height, forKey: .height)
|
||||
try container.encode(text, forKey: .text)
|
||||
try container.encode(placeholder, forKey: .placeholder)
|
||||
// try container.encode(placeholder, forKey: .placeholder)
|
||||
try container.encode(placeholderFontStyle, forKey: .placeholderFontStyle)
|
||||
try container.encode(textAlignment, forKey: .textAlignment)
|
||||
try container.encode(isEditable, forKey: .isEditable)
|
||||
try container.encode(borderWidth, forKey: .borderWidth)
|
||||
// try container.encode(borderWidth, forKey: .borderWidth)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user