Files
XRLib/Assets/Scripts/UVC/UIToolkit/Property/Items/UTKDatePropertyItem.cs
2026-02-03 20:43:36 +09:00

223 lines
6.3 KiB
C#

#nullable enable
using System;
using UnityEngine.UIElements;
namespace UVC.UIToolkit
{
/// <summary>
/// 날짜 속성 아이템
/// TextField + UTKDatePicker 연동
/// </summary>
public class UTKDatePropertyItem : UTKPropertyItemBase<DateTime>
{
#region Fields
private UTKInputField? _dateField;
private UTKButton? _pickerButton;
private UTKDatePicker? _currentPicker;
private string _dateFormat = "yyyy-MM-dd";
#endregion
#region Properties
public override UTKPropertyType PropertyType => UTKPropertyType.Date;
/// <summary>날짜 표시 형식</summary>
public string DateFormat
{
get => _dateFormat;
set
{
_dateFormat = value ?? "yyyy-MM-dd";
RefreshUI();
}
}
#endregion
#region Constructor
public UTKDatePropertyItem(string id, string name, DateTime initialValue = default, bool isReadOnly = false)
: base(id, name, initialValue == default ? DateTime.Today : initialValue)
{
base._isReadOnly = isReadOnly;
}
#endregion
#region Override Methods
public override VisualElement CreateUI()
{
var container = CreateUIFromUxml("UTKDatePropertyItem");
if (container == null)
{
return CreateUIFallback();
}
_dateField = container.Q<UTKInputField>("date-field");
_pickerButton = container.Q<UTKButton>("picker-btn");
if (_dateField != null)
{
_dateField.Value = Value.ToString(_dateFormat);
_dateField.isReadOnly = IsReadOnly;
}
if (_pickerButton != null)
{
_pickerButton.IsEnabled = !IsReadOnly;
}
return container;
}
private VisualElement CreateUIFallback()
{
var container = CreateContainer();
var label = CreateNameLabel();
container.Add(label);
var valueContainer = new VisualElement();
valueContainer.AddToClassList("utk-property-item__value");
_dateField = new UTKInputField();
_dateField.name = "date-field";
_dateField.Value = Value.ToString(_dateFormat);
_dateField.style.flexGrow = 1;
_dateField.isReadOnly = IsReadOnly;
valueContainer.Add(_dateField);
_pickerButton = new UTKButton("...", "", UTKButton.ButtonVariant.Secondary);
_pickerButton.name = "picker-btn";
_pickerButton.AddToClassList("utk-property-item__picker-btn");
_pickerButton.IsEnabled = !IsReadOnly;
valueContainer.Add(_pickerButton);
container.Add(valueContainer);
return container;
}
public override void BindUI(VisualElement element)
{
base.BindUI(element);
_dateField = element.Q<UTKInputField>("date-field");
_pickerButton = element.Q<UTKButton>("picker-btn");
if (_dateField != null)
{
_dateField.Value = Value.ToString(_dateFormat);
_dateField.isReadOnly = IsReadOnly;
_dateField.OnValueChanged += OnDateTextChanged;
}
if (_pickerButton != null)
{
_pickerButton.IsEnabled = !IsReadOnly;
_pickerButton.OnClicked += OnPickerButtonClicked;
}
}
public override void UnbindUI(VisualElement element)
{
if (_dateField != null)
{
_dateField.OnValueChanged -= OnDateTextChanged;
_dateField = null;
}
if (_pickerButton != null)
{
_pickerButton.OnClicked -= OnPickerButtonClicked;
_pickerButton = null;
}
ClosePicker();
base.UnbindUI(element);
}
public override void RefreshUI()
{
if (_dateField != null)
{
var formatted = Value.ToString(_dateFormat);
if (_dateField.Value != formatted)
{
_dateField.SetValue(formatted, false);
}
}
}
protected override void UpdateReadOnlyState()
{
base.UpdateReadOnlyState();
if (_dateField != null) _dateField.isReadOnly = IsReadOnly;
if (_pickerButton != null) _pickerButton.IsEnabled = !IsReadOnly;
}
#endregion
#region Private Methods
private void OnPickerButtonClicked()
{
OpenPicker();
}
private void OpenPicker()
{
if (_currentPicker != null || _rootElement == null) return;
var root = _rootElement;
while (root.parent != null)
{
root = root.parent;
}
_currentPicker = UTKDatePicker.Show(root, Value, UTKDatePicker.PickerMode.DateOnly, Name);
_currentPicker.OnDateSelected += OnPickerDateSelected;
_currentPicker.OnClosed += OnPickerClosed;
}
private void ClosePicker()
{
if (_currentPicker != null)
{
_currentPicker.OnDateSelected -= OnPickerDateSelected;
_currentPicker.OnClosed -= OnPickerClosed;
_currentPicker.Close();
_currentPicker = null;
}
}
private void OnPickerDateSelected(DateTime date)
{
Value = date.Date;
ClosePicker();
}
private void OnPickerClosed()
{
_currentPicker = null;
}
private void OnDateTextChanged(string newValue)
{
if (DateTime.TryParse(newValue, out DateTime date))
{
DebounceValueChange(date.Date, 500).Forget();
}
}
#endregion
#region IDisposable
protected override void Dispose(bool disposing)
{
if (disposing)
{
ClosePicker();
}
base.Dispose(disposing);
}
#endregion
}
}