123 lines
3.6 KiB
Swift
123 lines
3.6 KiB
Swift
//
|
|
// EditableTextField.swift
|
|
//
|
|
// Copyright (c) 2016 Touch Instinct
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
public enum EditableActionType {
|
|
case selectAll
|
|
case select
|
|
case cut
|
|
case copy
|
|
case paste
|
|
|
|
public static let allActions: [EditableActionType] = [.selectAll, .select, .cut, .paste, .copy]
|
|
}
|
|
|
|
open class EditableTextField: UITextField {
|
|
|
|
/// Actions, that will be disabled for this textField.
|
|
/// By default no actions are disabled.
|
|
open var disabledActions: [EditableActionType] = []
|
|
|
|
/// Allows to disable moving cursor for user
|
|
open var pinCursorToEnd: Bool = false
|
|
|
|
open var getType: (() -> TextType?)?
|
|
|
|
// MARK: - Private
|
|
|
|
private var disabledSelectors: [Selector] {
|
|
return disabledActions.map { selector(from: $0) }
|
|
}
|
|
|
|
private let menuSelectors = [
|
|
#selector(selectAll(_:)),
|
|
#selector(select(_:)),
|
|
#selector(cut(_:)),
|
|
#selector(copy(_:)),
|
|
#selector(paste(_:))
|
|
]
|
|
|
|
// MARK: - Overriden
|
|
|
|
override open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
|
|
if disabledSelectors.contains(action) {
|
|
return false
|
|
}
|
|
|
|
guard let type = getType?() else {
|
|
return super.canPerformAction(action, withSender: sender)
|
|
}
|
|
|
|
if case .date = type {
|
|
if menuSelectors.contains(action) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return super.canPerformAction(action, withSender: sender)
|
|
}
|
|
|
|
override open func caretRect(for position: UITextPosition) -> CGRect {
|
|
guard let type = getType?() else {
|
|
return super.caretRect(for: position)
|
|
}
|
|
|
|
if case .date = type {
|
|
return CGRect.null
|
|
}
|
|
|
|
return super.caretRect(for: position)
|
|
}
|
|
|
|
override open func closestPosition(to point: CGPoint) -> UITextPosition? {
|
|
if pinCursorToEnd {
|
|
return endOfDocument
|
|
}
|
|
|
|
return super.closestPosition(to: point)
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - Private extensions
|
|
|
|
private extension UITextField {
|
|
|
|
func selector(from actionTyoe: EditableActionType) -> Selector {
|
|
switch actionTyoe {
|
|
case .selectAll:
|
|
return #selector(selectAll(_:))
|
|
case .select:
|
|
return #selector(select(_:))
|
|
case .cut:
|
|
return #selector(cut(_:))
|
|
case .copy:
|
|
return #selector(copy(_:))
|
|
case .paste:
|
|
return #selector(paste(_:))
|
|
}
|
|
}
|
|
}
|