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

436 lines
15 KiB

// Copyright SIX DAY LLC. All rights reserved.
7 years ago
import Foundation
import UIKit
import Eureka
// MARK: FloatLabelCell
7 years ago
public class _FloatLabelCell<T>: Cell<T>, UITextFieldDelegate, TextFieldCell where T: Equatable, T: InputTypeInitiable {
7 years ago
public var textField: UITextField! { return floatLabelTextField }
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
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
}()
7 years ago
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())
}
7 years ago
open override func update() {
super.update()
textLabel?.text = nil
detailTextLabel?.text = nil
floatLabelTextField.attributedPlaceholder = NSAttributedString(string: row.title ?? "", attributes: [.foregroundColor: UIColor.lightGray])
7 years ago
floatLabelTextField.text = row.displayValueFor?(row.value)
floatLabelTextField.isEnabled = !row.isDisabled
floatLabelTextField.titleTextColour = .lightGray
floatLabelTextField.alpha = row.isDisabled ? 0.6 : 1
}
7 years ago
open override func cellCanBecomeFirstResponder() -> Bool {
return !row.isDisabled && floatLabelTextField.canBecomeFirstResponder
}
7 years ago
open override func cellBecomeFirstResponder(withDirection direction: Direction) -> Bool {
return floatLabelTextField.becomeFirstResponder()
}
7 years ago
open override func cellResignFirstResponder() -> Bool {
return floatLabelTextField.resignFirstResponder()
}
7 years ago
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
)
7 years ago
}
@objc public func textFieldDidChange(_ textField: UITextField) {
7 years ago
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 {
7 years ago
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
}
7 years ago
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)
}
7 years ago
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)
}
}
7 years ago
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 {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
public override func setup() {
super.setup()
textField?.autocorrectionType = .default
textField?.autocapitalizationType = .sentences
textField?.keyboardType = .default
}
}
public class IntFloatLabelCell: _FloatLabelCell<Int>, CellType {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
public override func setup() {
super.setup()
textField?.autocorrectionType = .default
textField?.autocapitalizationType = .none
textField?.keyboardType = .numberPad
}
}
public class PhoneFloatLabelCell: _FloatLabelCell<String>, CellType {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
public override func setup() {
super.setup()
textField?.keyboardType = .phonePad
}
}
public class NameFloatLabelCell: _FloatLabelCell<String>, CellType {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
public override func setup() {
super.setup()
textField.autocorrectionType = .no
textField.autocapitalizationType = .words
textField.keyboardType = .asciiCapable
}
}
public class EmailFloatLabelCell: _FloatLabelCell<String>, CellType {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
public override func setup() {
super.setup()
textField?.autocorrectionType = .no
textField?.autocapitalizationType = .none
textField?.keyboardType = .emailAddress
}
}
public class PasswordFloatLabelCell: _FloatLabelCell<String>, CellType {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
public override func setup() {
super.setup()
textField?.autocorrectionType = .no
textField?.autocapitalizationType = .none
textField?.keyboardType = .asciiCapable
textField?.isSecureTextEntry = true
}
}
public class DecimalFloatLabelCell: _FloatLabelCell<Float>, CellType {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
public override func setup() {
super.setup()
textField?.keyboardType = .decimalPad
}
}
public class URLFloatLabelCell: _FloatLabelCell<URL>, CellType {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
public override func setup() {
super.setup()
textField?.keyboardType = .URL
}
}
public class TwitterFloatLabelCell: _FloatLabelCell<String>, CellType {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
public override func setup() {
super.setup()
textField?.autocorrectionType = .no
textField?.autocapitalizationType = .none
textField?.keyboardType = .twitter
}
}
public class AccountFloatLabelCell: _FloatLabelCell<String>, CellType {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
public override func setup() {
super.setup()
textField?.autocorrectionType = .no
textField?.autocapitalizationType = .none
textField?.keyboardType = .asciiCapable
}
}
// MARK: FloatLabelRow
7 years ago
open class FloatFieldRow<Cell: CellType>: FormatteableRow<Cell> where Cell: BaseCell, Cell: TextFieldCell {
7 years ago
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 {
7 years ago
required public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
7 years ago
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
7 years ago
/// Image for selected state
lazy public var trueImage: UIImage = {
return UIImage(named: "selected")!
}()
7 years ago
/// Image for unselected state
lazy public var falseImage: UIImage = {
return UIImage(named: "unselected")!
}()
7 years ago
public override func update() {
super.update()
checkImageView?.image = row.value != nil ? trueImage : falseImage
checkImageView?.sizeToFit()
}
7 years ago
/// 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
}
7 years ago
guard let accessoryView = accessoryView else {
let imageView = UIImageView()
self.accessoryView = imageView
return imageView
}
7 years ago
return accessoryView as? UIImageView
}
7 years ago
public override func setup() {
super.setup()
accessoryType = .none
}
7 years ago
public override func didSelect() {
row.reload()
row.select()
row.deselect()
}
}