An advanced Ethereum/EVM mobile wallet
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
alpha-wallet-ios/Trust/UI/FloatLabelCell.swift

435 lines
15 KiB

// Copyright SIX DAY LLC. All rights reserved.
import Foundation
import UIKit
import Eureka
// MARK: FloatLabelCell
public class _FloatLabelCell<T>: Cell<T>, UITextFieldDelegate, TextFieldCell where T: Equatable, T: InputTypeInitiable {
public var textField: UITextField! { return floatLabelTextField }
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy public var floatLabelTextField: FloatLabelTextField = { [unowned self] in
let floatTextField = FloatLabelTextField()
floatTextField.translatesAutoresizingMaskIntoConstraints = false
floatTextField.font = .preferredFont(forTextStyle: .body)
floatTextField.titleFont = .boldSystemFont(ofSize: 11.0)
floatTextField.clearButtonMode = .whileEditing
return floatTextField
}()
open override func setup() {
super.setup()
height = { 55 }
selectionStyle = .none
contentView.addSubview(floatLabelTextField)
floatLabelTextField.delegate = self
floatLabelTextField.addTarget(self, action: #selector(_FloatLabelCell.textFieldDidChange(_:)), for: .editingChanged)
contentView.addConstraints(layoutConstraints())
}
open override func update() {
super.update()
textLabel?.text = nil
detailTextLabel?.text = nil
floatLabelTextField.attributedPlaceholder = NSAttributedString(string: row.title ?? "", attributes: [.foregroundColor: UIColor.lightGray])
floatLabelTextField.text = row.displayValueFor?(row.value)
floatLabelTextField.isEnabled = !row.isDisabled
floatLabelTextField.titleTextColour = .lightGray
floatLabelTextField.alpha = row.isDisabled ? 0.6 : 1
}
open override func cellCanBecomeFirstResponder() -> Bool {
return !row.isDisabled && floatLabelTextField.canBecomeFirstResponder
}
open override func cellBecomeFirstResponder(withDirection direction: Direction) -> Bool {
return floatLabelTextField.becomeFirstResponder()
}
open override func cellResignFirstResponder() -> Bool {
return floatLabelTextField.resignFirstResponder()
}
private func layoutConstraints() -> [NSLayoutConstraint] {
let views = ["floatLabeledTextField": floatLabelTextField]
let metrics = ["vMargin": 8.0]
return NSLayoutConstraint.constraints(
withVisualFormat: "H:|-[floatLabeledTextField]-|",
options: .alignAllLastBaseline,
metrics: metrics,
views: views
) +
NSLayoutConstraint.constraints(
withVisualFormat: "V:|-(vMargin)-[floatLabeledTextField]-(vMargin)-|",
options: .alignAllLastBaseline,
metrics: metrics,
views: views
)
}
@objc public func textFieldDidChange(_ textField: UITextField) {
guard let textValue = textField.text else {
row.value = nil
return
}
if let fieldRow = row as? FormatterConformance, let formatter = fieldRow.formatter {
if fieldRow.useFormatterDuringInput {
let value: AutoreleasingUnsafeMutablePointer<AnyObject?> = AutoreleasingUnsafeMutablePointer<AnyObject?>.init(UnsafeMutablePointer<T>.allocate(capacity: 1))
let errorDesc: AutoreleasingUnsafeMutablePointer<NSString?>? = nil
if formatter.getObjectValue(value, for: textValue, errorDescription: errorDesc) {
row.value = value.pointee as? T
if var selStartPos = textField.selectedTextRange?.start {
let oldVal = textField.text
textField.text = row.displayValueFor?(row.value)
if let f = formatter as? FormatterProtocol {
selStartPos = f.getNewPosition(forPosition: selStartPos, inTextInput: textField, oldValue: oldVal, newValue: textField.text)
}
textField.selectedTextRange = textField.textRange(from: selStartPos, to: selStartPos)
}
return
}
} else {
let value: AutoreleasingUnsafeMutablePointer<AnyObject?> = AutoreleasingUnsafeMutablePointer<AnyObject?>.init(UnsafeMutablePointer<T>.allocate(capacity: 1))
let errorDesc: AutoreleasingUnsafeMutablePointer<NSString?>? = nil
if formatter.getObjectValue(value, for: textValue, errorDescription: errorDesc) {
row.value = value.pointee as? T
}
return
}
}
guard !textValue.isEmpty else {
row.value = nil
return
}
guard let newValue = T.init(string: textValue) else {
return
}
row.value = newValue
}
private func displayValue(useFormatter: Bool) -> String? {
guard let v = row.value else { return nil }
if let formatter = (row as? FormatterConformance)?.formatter, useFormatter {
return textField?.isFirstResponder == true ? formatter.editingString(for: v) : formatter.string(for: v)
}
return String(describing: v)
}
public func textFieldDidBeginEditing(_ textField: UITextField) {
formViewController()?.beginEditing(of: self)
if let fieldRowConformance = row as? FormatterConformance, let _ = fieldRowConformance.formatter, fieldRowConformance.useFormatterOnDidBeginEditing ?? fieldRowConformance.useFormatterDuringInput {
textField.text = displayValue(useFormatter: true)
} else {
textField.text = displayValue(useFormatter: false)
}
}
public func textFieldDidEndEditing(_ textField: UITextField) {
formViewController()?.endEditing(of: self)
formViewController()?.textInputDidEndEditing(textField, cell: self)
textFieldDidChange(textField)
textField.text = displayValue(useFormatter: (row as? FormatterConformance)?.formatter != nil)
}
}
public class TextFloatLabelCell: _FloatLabelCell<String>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func setup() {
super.setup()
textField?.autocorrectionType = .default
textField?.autocapitalizationType = .sentences
textField?.keyboardType = .default
}
}
public class IntFloatLabelCell: _FloatLabelCell<Int>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func setup() {
super.setup()
textField?.autocorrectionType = .default
textField?.autocapitalizationType = .none
textField?.keyboardType = .numberPad
}
}
public class PhoneFloatLabelCell: _FloatLabelCell<String>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func setup() {
super.setup()
textField?.keyboardType = .phonePad
}
}
public class NameFloatLabelCell: _FloatLabelCell<String>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func setup() {
super.setup()
textField.autocorrectionType = .no
textField.autocapitalizationType = .words
textField.keyboardType = .asciiCapable
}
}
public class EmailFloatLabelCell: _FloatLabelCell<String>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func setup() {
super.setup()
textField?.autocorrectionType = .no
textField?.autocapitalizationType = .none
textField?.keyboardType = .emailAddress
}
}
public class PasswordFloatLabelCell: _FloatLabelCell<String>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func setup() {
super.setup()
textField?.autocorrectionType = .no
textField?.autocapitalizationType = .none
textField?.keyboardType = .asciiCapable
textField?.isSecureTextEntry = true
}
}
public class DecimalFloatLabelCell: _FloatLabelCell<Float>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func setup() {
super.setup()
textField?.keyboardType = .decimalPad
}
}
public class URLFloatLabelCell: _FloatLabelCell<URL>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func setup() {
super.setup()
textField?.keyboardType = .URL
}
}
public class TwitterFloatLabelCell: _FloatLabelCell<String>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func setup() {
super.setup()
textField?.autocorrectionType = .no
textField?.autocapitalizationType = .none
textField?.keyboardType = .twitter
}
}
public class AccountFloatLabelCell: _FloatLabelCell<String>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func setup() {
super.setup()
textField?.autocorrectionType = .no
textField?.autocapitalizationType = .none
textField?.keyboardType = .asciiCapable
}
}
// MARK: FloatLabelRow
open class FloatFieldRow<Cell: CellType>: FormatteableRow<Cell> where Cell: BaseCell, Cell: TextFieldCell {
public required init(tag: String?) {
super.init(tag: tag)
}
}
public final class TextFloatLabelRow: FloatFieldRow<TextFloatLabelCell>, RowType {
public required init(tag: String?) {
super.init(tag: tag)
}
}
public final class IntFloatLabelRow: FloatFieldRow<IntFloatLabelCell>, RowType {
public required init(tag: String?) {
super.init(tag: tag)
}
}
public final class DecimalFloatLabelRow: FloatFieldRow<DecimalFloatLabelCell>, RowType {
public required init(tag: String?) {
super.init(tag: tag)
}
}
public final class URLFloatLabelRow: FloatFieldRow<URLFloatLabelCell>, RowType {
public required init(tag: String?) {
super.init(tag: tag)
}
}
public final class TwitterFloatLabelRow: FloatFieldRow<TwitterFloatLabelCell>, RowType {
public required init(tag: String?) {
super.init(tag: tag)
}
}
public final class AccountFloatLabelRow: FloatFieldRow<AccountFloatLabelCell>, RowType {
public required init(tag: String?) {
super.init(tag: tag)
}
}
public final class PasswordFloatLabelRow: FloatFieldRow<PasswordFloatLabelCell>, RowType {
public required init(tag: String?) {
super.init(tag: tag)
}
}
public final class NameFloatLabelRow: FloatFieldRow<NameFloatLabelCell>, RowType {
public required init(tag: String?) {
super.init(tag: tag)
}
}
public final class EmailFloatLabelRow: FloatFieldRow<EmailFloatLabelCell>, RowType {
public required init(tag: String?) {
super.init(tag: tag)
}
}
public final class ImageCheckRow<T: Equatable>: Row<ImageCheckCell<T>>, SelectableRowType, RowType {
public var selectableValue: T?
required public init(tag: String?) {
super.init(tag: tag)
displayValueFor = nil
}
}
public class ImageCheckCell<T: Equatable> : Cell<T>, CellType {
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
/// Image for selected state
lazy public var trueImage: UIImage = {
return UIImage(named: "selected")!
}()
/// Image for unselected state
lazy public var falseImage: UIImage = {
return UIImage(named: "unselected")!
}()
public override func update() {
super.update()
checkImageView?.image = row.value != nil ? trueImage : falseImage
checkImageView?.sizeToFit()
}
/// Image view to render images. If `accessoryType` is set to `checkmark`
/// will create a new `UIImageView` and set it as `accessoryView`.
/// Otherwise returns `self.imageView`.
open var checkImageView: UIImageView? {
guard accessoryType == .checkmark else {
return self.imageView
}
guard let accessoryView = accessoryView else {
let imageView = UIImageView()
self.accessoryView = imageView
return imageView
}
return accessoryView as? UIImageView
}
public override func setup() {
super.setup()
accessoryType = .none
}
public override func didSelect() {
row.reload()
row.select()
row.deselect()
}
}