316 lines
10 KiB
C#
316 lines
10 KiB
C#
#nullable enable
|
|
using System;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace UVC.UIToolkit
|
|
{
|
|
/// <summary>
|
|
/// 날짜시간 범위 속성 아이템
|
|
/// 시작, 종료 두 개의 DateTimePicker
|
|
/// </summary>
|
|
public class UTKDateTimeRangePropertyItem : UTKPropertyItemBase<UTKDateTimeRange>
|
|
{
|
|
#region Fields
|
|
private UTKInputField? _startField;
|
|
private UTKInputField? _endField;
|
|
private UTKButton? _startPickerBtn;
|
|
private UTKButton? _endPickerBtn;
|
|
private UTKDatePicker? _currentPicker;
|
|
private bool _isEditingStart;
|
|
private string _dateTimeFormat = "yyyy-MM-dd HH:mm";
|
|
#endregion
|
|
|
|
#region Properties
|
|
public override UTKPropertyType PropertyType => UTKPropertyType.DateTimeRange;
|
|
|
|
public string DateTimeFormat
|
|
{
|
|
get => _dateTimeFormat;
|
|
set
|
|
{
|
|
_dateTimeFormat = value ?? "yyyy-MM-dd HH:mm";
|
|
RefreshUI();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Constructor
|
|
public UTKDateTimeRangePropertyItem(string id, string name, UTKDateTimeRange initialValue = default, bool isReadOnly = false)
|
|
: base(id, name, initialValue.Start == default ? new UTKDateTimeRange(DateTime.Now, DateTime.Now) : initialValue)
|
|
{
|
|
base._isReadOnly = isReadOnly;
|
|
}
|
|
|
|
public UTKDateTimeRangePropertyItem(string id, string name, DateTime start, DateTime end, bool isReadOnly = false)
|
|
: base(id, name, new UTKDateTimeRange(start, end))
|
|
{
|
|
base._isReadOnly = isReadOnly;
|
|
}
|
|
#endregion
|
|
|
|
#region Override Methods
|
|
public override VisualElement CreateUI()
|
|
{
|
|
var container = CreateUIFromUxml("UTKDateTimeRangePropertyItem");
|
|
if (container == null)
|
|
{
|
|
return CreateUIFallback();
|
|
}
|
|
|
|
_startField = container.Q<UTKInputField>("start-field");
|
|
_endField = container.Q<UTKInputField>("end-field");
|
|
_startPickerBtn = container.Q<UTKButton>("start-picker-btn");
|
|
_endPickerBtn = container.Q<UTKButton>("end-picker-btn");
|
|
|
|
if (_startField != null)
|
|
{
|
|
_startField.Value = Value.Start.ToString(_dateTimeFormat);
|
|
_startField.isReadOnly = IsReadOnly;
|
|
}
|
|
|
|
if (_endField != null)
|
|
{
|
|
_endField.Value = Value.End.ToString(_dateTimeFormat);
|
|
_endField.isReadOnly = IsReadOnly;
|
|
}
|
|
|
|
if (_startPickerBtn != null)
|
|
{
|
|
_startPickerBtn.IsEnabled = !IsReadOnly;
|
|
}
|
|
|
|
if (_endPickerBtn != null)
|
|
{
|
|
_endPickerBtn.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");
|
|
valueContainer.style.flexDirection = FlexDirection.Row;
|
|
|
|
// Start field
|
|
_startField = new UTKInputField();
|
|
_startField.name = "start-field";
|
|
_startField.Value = Value.Start.ToString(_dateTimeFormat);
|
|
_startField.style.flexGrow = 1;
|
|
_startField.isReadOnly = IsReadOnly;
|
|
valueContainer.Add(_startField);
|
|
|
|
_startPickerBtn = new UTKButton("...", "", UTKButton.ButtonVariant.Secondary);
|
|
_startPickerBtn.name = "start-picker-btn";
|
|
_startPickerBtn.IsEnabled = !IsReadOnly;
|
|
_startPickerBtn.AddToClassList("utk-property-item__picker-btn");
|
|
valueContainer.Add(_startPickerBtn);
|
|
|
|
var separator = new UTKLabel("~", UTKLabel.LabelSize.Body2);
|
|
separator.AddToClassList("utk-property-item__range-separator");
|
|
valueContainer.Add(separator);
|
|
|
|
// End field
|
|
_endField = new UTKInputField();
|
|
_endField.name = "end-field";
|
|
_endField.Value = Value.End.ToString(_dateTimeFormat);
|
|
_endField.style.flexGrow = 1;
|
|
_endField.isReadOnly = IsReadOnly;
|
|
valueContainer.Add(_endField);
|
|
|
|
_endPickerBtn = new UTKButton("...", "", UTKButton.ButtonVariant.Secondary);
|
|
_endPickerBtn.name = "end-picker-btn";
|
|
_endPickerBtn.IsEnabled = !IsReadOnly;
|
|
_endPickerBtn.AddToClassList("utk-property-item__picker-btn");
|
|
valueContainer.Add(_endPickerBtn);
|
|
|
|
container.Add(valueContainer);
|
|
|
|
return container;
|
|
}
|
|
|
|
public override void BindUI(VisualElement element)
|
|
{
|
|
base.BindUI(element);
|
|
|
|
_startField = element.Q<UTKInputField>("start-field");
|
|
_endField = element.Q<UTKInputField>("end-field");
|
|
_startPickerBtn = element.Q<UTKButton>("start-picker-btn");
|
|
_endPickerBtn = element.Q<UTKButton>("end-picker-btn");
|
|
|
|
if (_startField != null)
|
|
{
|
|
_startField.Value = Value.Start.ToString(_dateTimeFormat);
|
|
_startField.isReadOnly = IsReadOnly;
|
|
_startField.OnValueChanged += OnStartTextChanged;
|
|
}
|
|
|
|
if (_endField != null)
|
|
{
|
|
_endField.Value = Value.End.ToString(_dateTimeFormat);
|
|
_endField.isReadOnly = IsReadOnly;
|
|
_endField.OnValueChanged += OnEndTextChanged;
|
|
}
|
|
|
|
if (_startPickerBtn != null)
|
|
{
|
|
_startPickerBtn.IsEnabled = !IsReadOnly;
|
|
_startPickerBtn.OnClicked += OnStartPickerClicked;
|
|
}
|
|
|
|
if (_endPickerBtn != null)
|
|
{
|
|
_endPickerBtn.IsEnabled = !IsReadOnly;
|
|
_endPickerBtn.OnClicked += OnEndPickerClicked;
|
|
}
|
|
}
|
|
|
|
public override void UnbindUI(VisualElement element)
|
|
{
|
|
if (_startField != null)
|
|
{
|
|
_startField.OnValueChanged -= OnStartTextChanged;
|
|
_startField = null;
|
|
}
|
|
|
|
if (_endField != null)
|
|
{
|
|
_endField.OnValueChanged -= OnEndTextChanged;
|
|
_endField = null;
|
|
}
|
|
|
|
if (_startPickerBtn != null)
|
|
{
|
|
_startPickerBtn.OnClicked -= OnStartPickerClicked;
|
|
_startPickerBtn = null;
|
|
}
|
|
|
|
if (_endPickerBtn != null)
|
|
{
|
|
_endPickerBtn.OnClicked -= OnEndPickerClicked;
|
|
_endPickerBtn = null;
|
|
}
|
|
|
|
ClosePicker();
|
|
base.UnbindUI(element);
|
|
}
|
|
|
|
public override void RefreshUI()
|
|
{
|
|
if (_startField != null)
|
|
{
|
|
var formatted = Value.Start.ToString(_dateTimeFormat);
|
|
if (_startField.Value != formatted)
|
|
{
|
|
_startField.SetValue(formatted, false);
|
|
}
|
|
}
|
|
|
|
if (_endField != null)
|
|
{
|
|
var formatted = Value.End.ToString(_dateTimeFormat);
|
|
if (_endField.Value != formatted)
|
|
{
|
|
_endField.SetValue(formatted, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void UpdateReadOnlyState()
|
|
{
|
|
base.UpdateReadOnlyState();
|
|
|
|
if (_startField != null) _startField.isReadOnly = IsReadOnly;
|
|
if (_endField != null) _endField.isReadOnly = IsReadOnly;
|
|
if (_startPickerBtn != null) _startPickerBtn.IsEnabled = !IsReadOnly;
|
|
if (_endPickerBtn != null) _endPickerBtn.IsEnabled = !IsReadOnly;
|
|
}
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
private void OnStartPickerClicked()
|
|
{
|
|
_isEditingStart = true;
|
|
OpenPicker(Value.Start);
|
|
}
|
|
|
|
private void OnEndPickerClicked()
|
|
{
|
|
_isEditingStart = false;
|
|
OpenPicker(Value.End);
|
|
}
|
|
|
|
private void OpenPicker(DateTime initialDateTime)
|
|
{
|
|
if (_currentPicker != null || _rootElement == null) return;
|
|
|
|
var root = _rootElement;
|
|
while (root.parent != null) root = root.parent;
|
|
|
|
string title = _isEditingStart ? $"{Name} - 시작" : $"{Name} - 종료";
|
|
_currentPicker = UTKDatePicker.Show(root, initialDateTime, UTKDatePicker.PickerMode.DateAndTime, title);
|
|
_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 dateTime)
|
|
{
|
|
if (_isEditingStart)
|
|
{
|
|
Value = new UTKDateTimeRange(dateTime, Value.End);
|
|
}
|
|
else
|
|
{
|
|
Value = new UTKDateTimeRange(Value.Start, dateTime);
|
|
}
|
|
ClosePicker();
|
|
}
|
|
|
|
private void OnPickerClosed() => _currentPicker = null;
|
|
|
|
private void OnStartTextChanged(string newValue)
|
|
{
|
|
if (DateTime.TryParse(newValue, out DateTime dateTime))
|
|
{
|
|
var range = new UTKDateTimeRange(dateTime, Value.End);
|
|
DebounceValueChange(range, 500).Forget();
|
|
}
|
|
}
|
|
|
|
private void OnEndTextChanged(string newValue)
|
|
{
|
|
if (DateTime.TryParse(newValue, out DateTime dateTime))
|
|
{
|
|
var range = new UTKDateTimeRange(Value.Start, dateTime);
|
|
DebounceValueChange(range, 500).Forget();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region IDisposable
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing) ClosePicker();
|
|
base.Dispose(disposing);
|
|
}
|
|
#endregion
|
|
}
|
|
}
|