Files
UnrealEngine/Engine/Extras/VirtualProduction/LiveLinkVCAM/vcam/SingleValueViewController.swift
2025-05-18 13:04:45 +08:00

184 lines
5.7 KiB
Swift

//
// SingleValueViewController.swift
// Live Link VCAM
//
// Created by Brian Smith on 12/31/19.
// Copyright Epic Games, Inc. All Rights Reserved.
//
//
// The SingleValueViewController allows either the entry of a single value
// OR the editing of a value with an optional Delete button.
//
import UIKit
class SingleValueViewController : UITableViewController {
enum Mode {
case create
case edit
case editWithDelete
}
enum ActionType {
case done
case cancel
case delete
}
enum AllowedType {
case any
case ipAddress
case integer
case unreal // alphanumeric, _, -
}
@IBOutlet weak var textField: UITextField!
var doneButton: UIBarButtonItem?
var cancelButton: UIBarButtonItem?
var mode = Mode.create
var allowedType = AllowedType.any
var initialValue = String()
var placeholderValue : String?
var deleteLabelText : String?
var finished : ((ActionType, String?) -> Void)? = nil
private var isRoot = false
public private(set) var finishedAction = ActionType.cancel
override func viewDidLoad() {
super.viewDidLoad()
self.doneButton = UIBarButtonItem(title: mode == .create ? Localized.buttonAdd() : Localized.buttonDone(), style: .done, target: self, action: #selector(action))
// if this view is the root view of a nagivation controller, then we add a "cancel" and "done" button.
if self == self.navigationController?.viewControllers.first {
isRoot = true
self.cancelButton = UIBarButtonItem(title: Localized.buttonCancel(), style: .plain, target: self, action: #selector(action))
self.navigationItem.leftBarButtonItem = self.cancelButton
self.navigationItem.rightBarButtonItem = self.doneButton
} else {
if UIDevice.current.userInterfaceIdiom == .phone {
self.navigationItem.rightBarButtonItem = self.doneButton
}
// else the finishedAction is set to done always : this means that any dismissal (probably via
// a back gesture) of the VC is essentially a done/confirm
finishedAction = .done
}
self.textField.text = initialValue
self.textField.placeholder = self.placeholderValue
self.textField.delegate = self
switch allowedType {
case .integer:
self.textField.keyboardType = .numberPad
case .ipAddress:
self.textField.keyboardType = .numbersAndPunctuation
default:
break
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if #available(iOS 13.0, *) {
navigationController?.navigationBar.setNeedsLayout()
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.textField.becomeFirstResponder()
}
override func viewWillDisappear(_ animated: Bool) {
if let callback = finished {
callback(finishedAction, self.textField.text)
}
super.viewWillDisappear(animated)
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 1 {
self.textField.text = nil
self.finishedAction = .delete
if isRoot {
self.dismiss(animated: true, completion: nil)
} else {
self.navigationController?.popViewController(animated: true)
}
}
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// override the "delete" label if there was one specified
if indexPath.section == 1 {
if let text = deleteLabelText {
cell.textLabel?.text = text
}
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
if mode != .editWithDelete {
return 1
} else {
return super.numberOfSections(in: tableView)
}
}
@IBAction func action(sender : UIBarButtonItem) {
if sender == self.doneButton {
self.finishedAction = .done
}
// this action can only occur on a modal dialog
self.dismiss(animated: true, completion: nil)
}
func handleTextField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == self.textField {
switch allowedType {
case .integer:
let allowedCharacters = CharacterSet(charactersIn: "0123456789")
return allowedCharacters.isSuperset(of: CharacterSet(charactersIn: string))
case .ipAddress:
let allowedCharacters = CharacterSet(charactersIn: "0123456789.")
return allowedCharacters.isSuperset(of: CharacterSet(charactersIn: string))
case .unreal:
let allowedCharacters = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "-_"))
return allowedCharacters.isSuperset(of: CharacterSet(charactersIn: string))
default:
return true
}
}
return true
}
}
extension SingleValueViewController : UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return handleTextField(textField, shouldChangeCharactersIn: range, replacementString: string)
}
}