Adds steps logic for the register form.
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
@tool
|
||||
extends Control
|
||||
class_name FormValidator
|
||||
|
||||
signal control_validated(control, passed, messages)
|
||||
|
||||
class ValidatorInfo extends RefCounted:
|
||||
var control: Control
|
||||
var validator: Validator
|
||||
|
||||
@export var auto_validate: bool = false
|
||||
@export var validation_method: Validation.Method = Validation.Method.BATCH:
|
||||
set(value):
|
||||
validation_method = value
|
||||
_update_validation_methods()
|
||||
|
||||
var _control_validator_map: Dictionary = {}
|
||||
var _control_messages_map: Dictionary = {}
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
Validation.validator_added.connect(_on_validator_added)
|
||||
Validation.validator_removed.connect(_on_validator_removed)
|
||||
_find_validators(self)
|
||||
|
||||
|
||||
func get_messages() -> Dictionary:
|
||||
return _control_messages_map
|
||||
|
||||
|
||||
func get_messages_for_control(control: Control) -> PackedStringArray:
|
||||
if not _control_messages_map.has(control):
|
||||
return PackedStringArray()
|
||||
return _control_messages_map[control]
|
||||
|
||||
|
||||
func validate() -> bool:
|
||||
_control_messages_map.clear()
|
||||
var list = _get_validator_info_list()
|
||||
var valid = true
|
||||
for info in list:
|
||||
if info.validator.skip_validation:
|
||||
continue
|
||||
var passed = info.validator.validate(info.control)
|
||||
var messages = info.validator.get_messages()
|
||||
if not passed:
|
||||
_control_messages_map[info.control] = messages
|
||||
control_validated.emit(info.control, passed, messages)
|
||||
valid = valid and passed
|
||||
if not valid and validation_method == Validation.Method.IMMEDIATE:
|
||||
return valid
|
||||
return valid
|
||||
|
||||
|
||||
func _get_validator_info_list() -> Array[ValidatorInfo]:
|
||||
var list: Array[ValidatorInfo] = []
|
||||
for control in _control_validator_map.keys():
|
||||
var validator = _control_validator_map[control]
|
||||
if not validator:
|
||||
continue
|
||||
var info = ValidatorInfo.new()
|
||||
info.control = control
|
||||
info.validator = validator
|
||||
list.append(info)
|
||||
list.sort_custom(func (a: ValidatorInfo, b: ValidatorInfo):
|
||||
return a.validator.validation_order < b.validator.validation_order
|
||||
)
|
||||
return list
|
||||
|
||||
|
||||
func _update_validation_methods() -> void:
|
||||
var validators = _control_validator_map.values()
|
||||
for item in validators:
|
||||
var validator = item as Validator
|
||||
if not validator:
|
||||
continue
|
||||
validator.validation_method = validation_method
|
||||
|
||||
|
||||
func _find_validators(node: Node) -> void:
|
||||
for child in node.get_children():
|
||||
var control_validator = child as ControlValidator
|
||||
if control_validator:
|
||||
control_validator._on_validator_added()
|
||||
_find_validators(child)
|
||||
|
||||
|
||||
func _auto_validate(control: Control) -> void:
|
||||
if not auto_validate:
|
||||
return
|
||||
var validator = _control_validator_map[control] as Validator
|
||||
if not validator:
|
||||
return
|
||||
var passed = validator.validate(control)
|
||||
control_validated.emit(control, passed, validator.get_messages())
|
||||
|
||||
|
||||
func _on_validator_added(control: Control, validator: Validator) -> void:
|
||||
if not control:
|
||||
return
|
||||
_control_validator_map[control] = validator
|
||||
if not control.focus_exited.is_connected(_on_control_focus_exited):
|
||||
control.focus_exited.connect(_on_control_focus_exited.bind(control))
|
||||
# Special case to handle range-type controls that don't respond to focus
|
||||
# events for editing.
|
||||
if control.has_signal("value_changed"):
|
||||
if not control.value_changed.is_connected(_on_control_value_changed):
|
||||
control.value_changed.connect(_on_control_value_changed.bind(control))
|
||||
|
||||
|
||||
func _on_validator_removed(control: Control) -> void:
|
||||
_control_validator_map.erase(control)
|
||||
if control.focus_exited.is_connected(_on_control_focus_exited):
|
||||
control.focus_exited.disconnect(_on_control_focus_exited)
|
||||
if control.has_signal("value_changed"):
|
||||
if control.value_changed.is_connected(_on_control_value_changed):
|
||||
control.value_changed.disconnect(_on_control_value_changed)
|
||||
|
||||
|
||||
func _on_control_focus_exited(control: Control) -> void:
|
||||
_auto_validate(control)
|
||||
|
||||
|
||||
func _on_control_value_changed(value: float, control: Control) -> void:
|
||||
_auto_validate(control)
|
||||
Reference in New Issue
Block a user