Files
XRLib/Assets/Scripts/UVC/UI/Window/PropertyWindow/UI/DateTimeRangePropertyUI.cs
2025-09-25 16:31:52 +09:00

287 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UVC.Extention;
using UVC.UI.Modal.DatePicker;
using UVC.UI.Tooltip;
using UVC.Util;
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 TMP_InputField _startDateText; // 시작 날짜 표시
[SerializeField]
private Button _startDatePickerButton; // 시작 날짜/시간 선택 버튼
[SerializeField]
private TMP_Dropdown _startHourDropDown; // 선택된 시간을 표시
[SerializeField]
private TMP_Dropdown _startMiniteDropDown; // 선택된 분을 표시
[SerializeField]
private TMP_InputField _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"; // 날짜 표시 형식
private const string FullDateFormat = "yyyy-MM-dd HH:mm:ss"; // 날짜 표시 형식
/// <summary>
/// PropertyView에 의해 호출되어 UI를 초기화하고 데이터를 설정합니다.
/// </summary>
public void Setup(IPropertyItem item, PropertyWindow controller)
{
if (!(item is DateTimeRangeProperty dateTimeRangeItem))
{
Debug.LogError($"DateTimeRangePropertyUI에 잘못된 타입의 PropertyItem이 전달되었습니다. {item.GetType()}");
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);
_startHourDropDown.SetValueWithoutNotify(_propertyItem.Value.Item1.Hour);
_startMiniteDropDown.SetValueWithoutNotify(_propertyItem.Value.Item1.Minute);
_endHourDropDown.SetValueWithoutNotify(_propertyItem.Value.Item2.Hour);
_endMiniteDropDown.SetValueWithoutNotify(_propertyItem.Value.Item2.Minute);
// --- 데이터 바인딩 ---
_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.Item1.ToString(DateFormat);
_endDateText.text = _propertyItem.Value.Item2.ToString(DateFormat);
// 읽기 전용 상태 설정
bool isReadOnly = _propertyItem.IsReadOnly;
_startDateText.interactable = !isReadOnly;
_endDateText.interactable = !isReadOnly;
_startDatePickerButton.interactable = !isReadOnly;
_endDatePickerButton.interactable = !isReadOnly;
_startDatePickerButton.gameObject.SetActive(!isReadOnly);
_endDatePickerButton.gameObject.SetActive(!isReadOnly);
// --- 이벤트 리스너 등록 ---
_startDatePickerButton.onClick.RemoveAllListeners();
_endDatePickerButton.onClick.RemoveAllListeners();
_startDatePickerButton.onClick.AddListener(OpenStartDateTimePicker);
_endDatePickerButton.onClick.AddListener(OpenEndDateTimePicker);
_startHourDropDown.interactable = !isReadOnly;
_startHourDropDown.onValueChanged.RemoveAllListeners();
_startHourDropDown.onValueChanged.AddListener((int hour) =>
{
DateTime newDateTime = new DateTime(
_propertyItem.Value.Item1.Year,
_propertyItem.Value.Item1.Month,
_propertyItem.Value.Item1.Day,
hour,
_propertyItem.Value.Item1.Minute,
0
);
OnStartDateTimeSelected(newDateTime);
});
_startMiniteDropDown.interactable = !isReadOnly;
_startMiniteDropDown.onValueChanged.RemoveAllListeners();
_startMiniteDropDown.onValueChanged.AddListener((int minute) =>
{
DateTime newDateTime = new DateTime(
_propertyItem.Value.Item1.Year,
_propertyItem.Value.Item1.Month,
_propertyItem.Value.Item1.Day,
_propertyItem.Value.Item1.Hour,
minute,
0
);
OnStartDateTimeSelected(newDateTime);
});
_endHourDropDown.interactable = !isReadOnly;
_endHourDropDown.onValueChanged.RemoveAllListeners();
_endHourDropDown.onValueChanged.AddListener((int hour) =>
{
DateTime newDateTime = new DateTime(
_propertyItem.Value.Item2.Year,
_propertyItem.Value.Item2.Month,
_propertyItem.Value.Item2.Day,
hour,
_propertyItem.Value.Item2.Minute,
0
);
OnEndDateTimeSelected(newDateTime);
});
_endMiniteDropDown.interactable = !isReadOnly;
_endMiniteDropDown.onValueChanged.RemoveAllListeners();
_endMiniteDropDown.onValueChanged.AddListener((int minute) =>
{
DateTime newDateTime = new DateTime(
_propertyItem.Value.Item2.Year,
_propertyItem.Value.Item2.Month,
_propertyItem.Value.Item2.Day,
_propertyItem.Value.Item2.Hour,
minute,
0
);
OnEndDateTimeSelected(newDateTime);
});
}
private async void OpenStartDateTimePicker()
{
CursorManager.Instance.SetDefaultCursor();
await DatePicker.Show(_propertyItem.Value.Item1, newDate =>
{
DateTime newDateTime = new DateTime(
newDate.Year,
newDate.Month,
newDate.Day,
_propertyItem.Value.Item1.Hour,
_propertyItem.Value.Item1.Minute,
0
);
OnStartDateTimeSelected(newDateTime);
});
CursorManager.Instance.SetDefaultCursor();
Debug.LogWarning($"'{_propertyItem.Name}'의 시작 날짜/시간 선택기 로직이 구현되지 않았습니다.");
}
private async void OpenEndDateTimePicker()
{
CursorManager.Instance.SetDefaultCursor();
await DatePicker.Show(_propertyItem.Value.Item2, newDate =>
{
DateTime newDateTime = new DateTime(
newDate.Year,
newDate.Month,
newDate.Day,
_propertyItem.Value.Item2.Hour,
_propertyItem.Value.Item2.Minute,
0
);
OnEndDateTimeSelected(newDateTime);
});
CursorManager.Instance.SetDefaultCursor();
Debug.LogWarning($"'{_propertyItem.Name}'의 끝 날짜/시간 선택기 로직이 구현되지 않았습니다.");
}
private void OnStartDateTimeSelected(DateTime newStartDateTime)
{
//이전 값이랑 같으면 리턴
if (_propertyItem.Value.Item1.ToString(FullDateFormat) == newStartDateTime.ToString(FullDateFormat)) return;
DateTime Item1 = newStartDateTime;
DateTime Item2 = _propertyItem.Value.Item2;
// 시작 날짜/시간이 끝 날짜/시간보다 늦어지지 않도록 보정
if (newStartDateTime > Item2) Item2 = newStartDateTime;
var newValue = new Tuple<DateTime, DateTime>(Item1, Item2);
// UI 업데이트
_startDateText.text = Item1.ToString(DateFormat);
_endDateText.text = Item2.ToString(DateFormat);
_startHourDropDown.SetValueWithoutNotify(Item1.Hour);
_startMiniteDropDown.SetValueWithoutNotify(Item1.Minute);
_endHourDropDown.SetValueWithoutNotify(Item2.Hour);
_endMiniteDropDown.SetValueWithoutNotify(Item2.Minute);
// 변경 이벤트 알림
_controller.UpdatePropertyValue(_propertyItem.Id, _propertyItem.PropertyType, newValue);
}
private void OnEndDateTimeSelected(DateTime newEndDateTime)
{
//이전 값이랑 같으면 리턴
if (_propertyItem.Value.Item2.ToString(FullDateFormat) == newEndDateTime.ToString(FullDateFormat)) return;
DateTime Item1 = _propertyItem.Value.Item1;
DateTime Item2 = newEndDateTime;
// 끝 날짜/시간이 시작 날짜/시간보다 빨라지지 않도록 보정
if (newEndDateTime < Item1) Item1 = newEndDateTime;
var newValue = new Tuple<DateTime, DateTime>(Item1, Item2);
// UI 업데이트
_startDateText.text = Item1.ToString(DateFormat);
_endDateText.text = Item2.ToString(DateFormat);
_startHourDropDown.SetValueWithoutNotify(Item1.Hour);
_startMiniteDropDown.SetValueWithoutNotify(Item1.Minute);
_endHourDropDown.SetValueWithoutNotify(Item2.Hour);
_endMiniteDropDown.SetValueWithoutNotify(Item2.Minute);
// 변경 이벤트 알림
_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();
}
}
}