Files
XRLib/Assets/Scripts/UVC/UI/Window/PropertyWindow/UI/DateTimeRangePropertyUI.cs
2025-09-22 20:12:56 +09:00

240 lines
9.6 KiB
C#

using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UVC.Extention;
using UVC.UI.Modal;
using UVC.UI.Modal.DatePicker;
using UVC.UI.Tooltip;
namespace UVC.UI.Window.PropertyWindow.UI
{
/// <summary>
/// DateTimeRangeProperty를 위한 UI를 제어하는 스크립트입니다.
/// 범위의 시작 날짜/시간과 끝 날짜/시간을 별도의 버튼으로 관리합니다.
/// </summary>
[RequireComponent(typeof(LayoutElement))]
public class DateTimeRangePropertyUI : MonoBehaviour, IPropertyUI
{
[Header("UI Components")]
[SerializeField]
private TextMeshProUGUI _nameLabel; // 속성 전체 이름
[SerializeField]
private TextMeshProUGUI _descriptionLabel;
[SerializeField]
private TextMeshProUGUI _startDateText; // 시작 날짜 표시
[SerializeField]
private Button _startDatePickerButton; // 시작 날짜/시간 선택 버튼
[SerializeField]
private TMP_Dropdown _startHourDropDown; // 선택된 시간을 표시
[SerializeField]
private TMP_Dropdown _startMiniteDropDown; // 선택된 분을 표시
[SerializeField]
private TextMeshProUGUI _endDateText; // 끝 날짜/시간 표시
[SerializeField]
private Button _endDatePickerButton; // 끝 날짜/시간 선택 버튼
[SerializeField]
private TMP_Dropdown _endHourDropDown; // 선택된 시간을 표시
[SerializeField]
private TMP_Dropdown _endMiniteDropDown; // 선택된 분을 표시
private DateTimeRangeProperty _propertyItem;
private PropertyWindow _controller;
private const string DateFormat = "yyyy-MM-dd"; // 날짜 표시 형식
/// <summary>
/// PropertyView에 의해 호출되어 UI를 초기화하고 데이터를 설정합니다.
/// </summary>
public void Setup(IPropertyItem item, PropertyWindow controller)
{
if (!(item is DateTimeRangeProperty dateTimeRangeItem))
{
Debug.LogError("DateTimeRangePropertyUI에 잘못된 타입의 PropertyItem이 전달되었습니다.");
return;
}
_propertyItem = dateTimeRangeItem;
_controller = controller;
List<string> hourOptions = new List<string>();
List<string> minuteOptions = new List<string>();
for (int i = 0; i < 60; i++)
{
if (i < 24) hourOptions.Add(i.ToString("D2"));
minuteOptions.Add(i.ToString("D2"));
}
_startHourDropDown.AddOptions(hourOptions);
_startMiniteDropDown.AddOptions(minuteOptions);
_endHourDropDown.AddOptions(hourOptions);
_endMiniteDropDown.AddOptions(minuteOptions);
// --- 데이터 바인딩 ---
_nameLabel.text = _propertyItem.Name;
// 툴팁 설정 (TooltipHandler 컴포넌트가 있다면 연동)
TooltipHandler tooltipHandler = _nameLabel.GetComponent<TooltipHandler>();
if (tooltipHandler != null && !_propertyItem.Tooltip.IsNullOrEmpty())
{
tooltipHandler.Tooltip = _propertyItem.Tooltip;
}
if (_propertyItem.Description.IsNullOrEmpty())
{
_descriptionLabel.gameObject.SetActive(false);
}
else
{
_descriptionLabel.gameObject.SetActive(true);
_descriptionLabel.text = _propertyItem.Description;
}
// 초기 값 설정
_startDateText.text = _propertyItem.Value.ToString(DateFormat);
_endDateText.text = _propertyItem.Value2.ToString(DateFormat);
// 읽기 전용 상태 설정
bool isReadOnly = _propertyItem.IsReadOnly;
_startDatePickerButton.interactable = !isReadOnly;
_endDatePickerButton.interactable = !isReadOnly;
// --- 이벤트 리스너 등록 ---
_startDatePickerButton.onClick.RemoveAllListeners();
_endDatePickerButton.onClick.RemoveAllListeners();
_startDatePickerButton.onClick.AddListener(OpenStartDateTimePicker);
_endDatePickerButton.onClick.AddListener(OpenEndDateTimePicker);
_startHourDropDown.onValueChanged.RemoveAllListeners();
_startHourDropDown.onValueChanged.AddListener((int hour) => {
if (_propertyItem.GetValue() is DateTime currentDateTime)
{
DateTime newDateTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
hour,
currentDateTime.Minute,
currentDateTime.Second
);
OnStartDateTimeSelected(newDateTime);
}
});
_startMiniteDropDown.onValueChanged.RemoveAllListeners();
_startMiniteDropDown.onValueChanged.AddListener((int minute) => {
if (_propertyItem.GetValue() is DateTime currentDateTime)
{
DateTime newDateTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
currentDateTime.Hour,
minute,
currentDateTime.Second
);
OnStartDateTimeSelected(newDateTime);
}
});
_endHourDropDown.onValueChanged.RemoveAllListeners();
_endHourDropDown.onValueChanged.AddListener((int hour) => {
if (_propertyItem.GetValue() is DateTime currentDateTime)
{
DateTime newDateTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
hour,
currentDateTime.Minute,
currentDateTime.Second
);
OnEndDateTimeSelected(newDateTime);
}
});
_endMiniteDropDown.onValueChanged.RemoveAllListeners();
_endMiniteDropDown.onValueChanged.AddListener((int minute) => {
if (_propertyItem.GetValue() is DateTime currentDateTime)
{
DateTime newDateTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
currentDateTime.Hour,
minute,
currentDateTime.Second
);
OnEndDateTimeSelected(newDateTime);
}
});
}
private void OpenStartDateTimePicker()
{
DatePicker.Show(_propertyItem.Value, OnStartDateTimeSelected);
Debug.LogWarning($"'{_propertyItem.Name}'의 시작 날짜/시간 선택기 로직이 구현되지 않았습니다.");
}
private void OpenEndDateTimePicker()
{
DatePicker.Show(_propertyItem.Value2, OnEndDateTimeSelected);
Debug.LogWarning($"'{_propertyItem.Name}'의 끝 날짜/시간 선택기 로직이 구현되지 않았습니다.");
}
private void OnStartDateTimeSelected(DateTime newStartDateTime)
{
var oldValue = new Tuple<DateTime, DateTime>(_propertyItem.Value, _propertyItem.Value2);
// 시작 날짜/시간이 끝 날짜/시간보다 늦어지지 않도록 보정
if (newStartDateTime > _propertyItem.Value2)
{
_propertyItem.Value2 = newStartDateTime;
}
_propertyItem.Value = newStartDateTime;
var newValue = new Tuple<DateTime, DateTime>(_propertyItem.Value, _propertyItem.Value2);
// UI 업데이트
_startDateText.text = _propertyItem.Value.ToString(DateFormat);
_endDateText.text = _propertyItem.Value2.ToString(DateFormat);
// 변경 이벤트 알림
_controller.UpdatePropertyValue(_propertyItem.Id, _propertyItem.PropertyType, newValue);
}
private void OnEndDateTimeSelected(DateTime newEndDateTime)
{
var oldValue = new Tuple<DateTime, DateTime>(_propertyItem.Value, _propertyItem.Value2);
// 끝 날짜/시간이 시작 날짜/시간보다 빨라지지 않도록 보정
if (newEndDateTime < _propertyItem.Value)
{
_propertyItem.Value = newEndDateTime;
}
_propertyItem.Value2 = newEndDateTime;
var newValue = new Tuple<DateTime, DateTime>(_propertyItem.Value, _propertyItem.Value2);
// UI 업데이트
_startDateText.text = _propertyItem.Value.ToString(DateFormat);
_endDateText.text = _propertyItem.Value2.ToString(DateFormat);
// 변경 이벤트 알림
_controller.UpdatePropertyValue(_propertyItem.Id, _propertyItem.PropertyType, newValue);
}
/// <summary>
/// 이 UI 오브젝트가 파괴될 때 Unity에 의해 호출됩니다.
/// </summary>
private void OnDestroy()
{
if (_startDatePickerButton != null) _startDatePickerButton.onClick.RemoveAllListeners();
if (_endDatePickerButton != null) _endDatePickerButton.onClick.RemoveAllListeners();
}
}
}