415 lines
14 KiB
C#
415 lines
14 KiB
C#
#nullable enable
|
|
using System;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using UVC.Locale;
|
|
using UVC.UIToolkit;
|
|
|
|
namespace UVC.Sample.UIToolkit
|
|
{
|
|
/// <summary>
|
|
/// UTKDatePicker 샘플 코드
|
|
/// 버튼 클릭으로 날짜 피커를 열고 선택된 날짜를 표시
|
|
/// </summary>
|
|
public class UTKDatePickerSample : MonoBehaviour
|
|
{
|
|
[SerializeField] private UIDocument? _uiDocument;
|
|
|
|
[SerializeField]
|
|
[Tooltip("시작 시 적용할 테마")]
|
|
private UTKTheme initialTheme = UTKTheme.Dark;
|
|
|
|
private UTKToggle _themeToggle;
|
|
|
|
private VisualElement? _root;
|
|
private Label? _dateLabel;
|
|
private Label? _dateTimeLabel;
|
|
private Label? _dateRangeLabel;
|
|
|
|
private DateTime _selectedDate = DateTime.Today;
|
|
private DateTime _selectedDateTime = DateTime.Now;
|
|
private DateTime _rangeStartDate = DateTime.Today;
|
|
private DateTime _rangeEndDate = DateTime.Today.AddDays(7);
|
|
private UTKDatePicker? _currentPicker;
|
|
|
|
private void Start()
|
|
{
|
|
// UIDocument 참조 확인
|
|
var doc = GetComponent<UIDocument>();
|
|
if (doc == null)
|
|
{
|
|
Debug.LogError("UIDocument가 할당되지 않았습니다.");
|
|
return;
|
|
}
|
|
_uiDocument = doc;
|
|
|
|
var toggle = _uiDocument.rootVisualElement.Q<UTKToggle>("toggle");
|
|
if (toggle == null)
|
|
{
|
|
Debug.LogError("UXML에서 UTKToggle을 찾을 수 없습니다.");
|
|
return;
|
|
}
|
|
_themeToggle = toggle;
|
|
|
|
UTKThemeManager.Instance.RegisterRoot(_uiDocument.rootVisualElement);
|
|
UTKThemeManager.Instance.SetTheme(initialTheme);
|
|
|
|
_themeToggle.OnValueChanged += (isOn) =>
|
|
{
|
|
UTKThemeManager.Instance.SetTheme(!isOn ? UTKTheme.Dark : UTKTheme.Light);
|
|
};
|
|
|
|
bool success = LocalizationManager.Instance.LoadDefaultLocalizationData("ko", "locale.json");
|
|
Debug.Log($"LocalizationManager: LoadDefaultLocalizationData success: {success}");
|
|
|
|
_root = _uiDocument.rootVisualElement;
|
|
UTKDatePicker.SetRoot(_root);
|
|
CreateSampleUI();
|
|
}
|
|
|
|
private void CreateSampleUI()
|
|
{
|
|
if (_root == null) return;
|
|
|
|
// 메인 컨테이너
|
|
var container = new VisualElement();
|
|
container.style.position = Position.Absolute;
|
|
container.style.left = 20;
|
|
container.style.top = 20;
|
|
container.style.backgroundColor = new Color(0.2f, 0.2f, 0.2f);
|
|
container.style.borderTopLeftRadius = 8;
|
|
container.style.borderTopRightRadius = 8;
|
|
container.style.borderBottomLeftRadius = 8;
|
|
container.style.borderBottomRightRadius = 8;
|
|
container.style.paddingTop = 15;
|
|
container.style.paddingBottom = 15;
|
|
container.style.paddingLeft = 15;
|
|
container.style.paddingRight = 15;
|
|
container.style.width = 320;
|
|
|
|
// 타이틀
|
|
var title = new Label("UTKDatePicker Sample");
|
|
title.style.fontSize = 16;
|
|
title.style.unityFontStyleAndWeight = FontStyle.Bold;
|
|
title.style.color = Color.white;
|
|
title.style.marginBottom = 15;
|
|
container.Add(title);
|
|
|
|
// Date Only 섹션
|
|
var dateSection = CreateSection("Date Only Mode", "Open Date Picker", OpenDatePicker);
|
|
_dateLabel = dateSection.label;
|
|
_dateLabel.text = FormatDate(_selectedDate);
|
|
container.Add(dateSection.container);
|
|
|
|
// DateTime 섹션
|
|
var dateTimeSection = CreateSection("Date & Time Mode", "Open DateTime Picker", OpenDateTimePicker);
|
|
_dateTimeLabel = dateTimeSection.label;
|
|
_dateTimeLabel.text = FormatDateTime(_selectedDateTime);
|
|
container.Add(dateTimeSection.container);
|
|
|
|
// Async 섹션
|
|
var asyncSection = new VisualElement();
|
|
asyncSection.style.marginBottom = 15;
|
|
|
|
var asyncLabel = new Label("Async/Await Mode");
|
|
asyncLabel.style.color = new Color(0.8f, 0.8f, 0.8f);
|
|
asyncLabel.style.fontSize = 12;
|
|
asyncLabel.style.marginBottom = 5;
|
|
asyncSection.Add(asyncLabel);
|
|
|
|
var asyncBtn = new Button(() => OpenDatePickerAsync().Forget()) { text = "Open Date Picker (Async)" };
|
|
asyncBtn.style.height = 32;
|
|
asyncSection.Add(asyncBtn);
|
|
|
|
container.Add(asyncSection);
|
|
|
|
// Date Range 섹션
|
|
var rangeSection = CreateSection("Date Range Mode", "Open Range Picker", OpenDateRangePicker);
|
|
_dateRangeLabel = rangeSection.label;
|
|
_dateRangeLabel.text = FormatDateRange(_rangeStartDate, _rangeEndDate);
|
|
container.Add(rangeSection.container);
|
|
|
|
// Date Range Async 섹션
|
|
var rangeAsyncSection = new VisualElement();
|
|
rangeAsyncSection.style.marginBottom = 15;
|
|
|
|
var rangeAsyncLabel = new Label("Date Range Async Mode");
|
|
rangeAsyncLabel.style.color = new Color(0.8f, 0.8f, 0.8f);
|
|
rangeAsyncLabel.style.fontSize = 12;
|
|
rangeAsyncLabel.style.marginBottom = 5;
|
|
rangeAsyncSection.Add(rangeAsyncLabel);
|
|
|
|
var rangeAsyncBtn = new Button(() => OpenDateRangePickerAsync().Forget()) { text = "Open Range Picker (Async)" };
|
|
rangeAsyncBtn.style.height = 32;
|
|
rangeAsyncSection.Add(rangeAsyncBtn);
|
|
|
|
container.Add(rangeAsyncSection);
|
|
|
|
// 구분선
|
|
var separator = new VisualElement();
|
|
separator.style.height = 1;
|
|
separator.style.backgroundColor = new Color(0.4f, 0.4f, 0.4f);
|
|
separator.style.marginTop = 15;
|
|
separator.style.marginBottom = 15;
|
|
container.Add(separator);
|
|
|
|
// 프리셋 날짜 버튼들
|
|
var presetLabel = new Label("Quick Select:");
|
|
presetLabel.style.color = Color.white;
|
|
presetLabel.style.marginBottom = 10;
|
|
container.Add(presetLabel);
|
|
|
|
var presetRow = new VisualElement();
|
|
presetRow.style.flexDirection = FlexDirection.Row;
|
|
presetRow.style.flexWrap = Wrap.Wrap;
|
|
|
|
AddPresetButton(presetRow, "Today", DateTime.Today);
|
|
AddPresetButton(presetRow, "Tomorrow", DateTime.Today.AddDays(1));
|
|
AddPresetButton(presetRow, "Next Week", DateTime.Today.AddDays(7));
|
|
AddPresetButton(presetRow, "Next Month", DateTime.Today.AddMonths(1));
|
|
|
|
container.Add(presetRow);
|
|
|
|
_root.Add(container);
|
|
}
|
|
|
|
private (VisualElement container, Label label) CreateSection(string sectionTitle, string buttonText, Action onClick)
|
|
{
|
|
var section = new VisualElement();
|
|
section.style.marginBottom = 15;
|
|
|
|
var sectionLabel = new Label(sectionTitle);
|
|
sectionLabel.style.color = new Color(0.8f, 0.8f, 0.8f);
|
|
sectionLabel.style.fontSize = 12;
|
|
sectionLabel.style.marginBottom = 5;
|
|
section.Add(sectionLabel);
|
|
|
|
var row = new VisualElement();
|
|
row.style.flexDirection = FlexDirection.Row;
|
|
row.style.alignItems = Align.Center;
|
|
|
|
var valueLabel = new Label();
|
|
valueLabel.style.color = Color.white;
|
|
valueLabel.style.fontSize = 14;
|
|
valueLabel.style.flexGrow = 1;
|
|
valueLabel.style.paddingTop = 5;
|
|
valueLabel.style.paddingBottom = 5;
|
|
valueLabel.style.paddingLeft = 10;
|
|
valueLabel.style.paddingRight = 10;
|
|
valueLabel.style.backgroundColor = new Color(0.15f, 0.15f, 0.15f);
|
|
valueLabel.style.borderTopLeftRadius = 4;
|
|
valueLabel.style.borderTopRightRadius = 4;
|
|
valueLabel.style.borderBottomLeftRadius = 4;
|
|
valueLabel.style.borderBottomRightRadius = 4;
|
|
row.Add(valueLabel);
|
|
|
|
var button = new Button(onClick) { text = buttonText };
|
|
button.style.marginLeft = 10;
|
|
button.style.height = 28;
|
|
row.Add(button);
|
|
|
|
section.Add(row);
|
|
|
|
return (section, valueLabel);
|
|
}
|
|
|
|
private void AddPresetButton(VisualElement parent, string label, DateTime date)
|
|
{
|
|
var btn = new Button(() => SetDate(date)) { text = label };
|
|
btn.style.marginRight = 5;
|
|
btn.style.marginBottom = 5;
|
|
btn.style.height = 28;
|
|
parent.Add(btn);
|
|
}
|
|
|
|
private void OpenDatePicker()
|
|
{
|
|
if (_root == null || _currentPicker != null) return;
|
|
|
|
_currentPicker = UTKDatePicker.Show(
|
|
_selectedDate,
|
|
UTKDatePicker.PickerMode.DateOnly,
|
|
"Select Date"
|
|
);
|
|
|
|
_currentPicker.OnDateSelected += OnDateSelected;
|
|
_currentPicker.OnClosed += OnPickerClosed;
|
|
}
|
|
|
|
private void OpenDateTimePicker()
|
|
{
|
|
if (_root == null || _currentPicker != null) return;
|
|
|
|
_currentPicker = UTKDatePicker.Show(
|
|
_selectedDateTime,
|
|
UTKDatePicker.PickerMode.DateAndTime,
|
|
"Select Date & Time"
|
|
);
|
|
|
|
_currentPicker.OnDateSelected += OnDateTimeSelected;
|
|
_currentPicker.OnClosed += OnPickerClosed;
|
|
}
|
|
|
|
private async UniTaskVoid OpenDatePickerAsync()
|
|
{
|
|
if (_root == null) return;
|
|
|
|
// ShowAsync를 사용하여 날짜 선택 대기
|
|
// OK 클릭 시 선택된 날짜 반환, 취소/닫기 시 null 반환
|
|
DateTime? result = await UTKDatePicker.ShowAsync(
|
|
_selectedDate,
|
|
UTKDatePicker.PickerMode.DateOnly,
|
|
"Select Date (Async)"
|
|
);
|
|
|
|
if (result.HasValue)
|
|
{
|
|
_selectedDate = result.Value;
|
|
if (_dateLabel != null)
|
|
{
|
|
_dateLabel.text = FormatDate(result.Value);
|
|
}
|
|
Debug.Log($"[Async] Date Result: {FormatDate(result.Value)}");
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("[Async] Date selection cancelled");
|
|
}
|
|
}
|
|
|
|
private void OnDateSelected(DateTime date)
|
|
{
|
|
_selectedDate = date;
|
|
if (_dateLabel != null)
|
|
{
|
|
_dateLabel.text = FormatDate(date);
|
|
}
|
|
Debug.Log($"Date Selected: {FormatDate(date)}");
|
|
}
|
|
|
|
private void OnDateTimeSelected(DateTime dateTime)
|
|
{
|
|
_selectedDateTime = dateTime;
|
|
if (_dateTimeLabel != null)
|
|
{
|
|
_dateTimeLabel.text = FormatDateTime(dateTime);
|
|
}
|
|
Debug.Log($"DateTime Selected: {FormatDateTime(dateTime)}");
|
|
}
|
|
|
|
private void OnPickerClosed()
|
|
{
|
|
if (_currentPicker != null)
|
|
{
|
|
_currentPicker.OnDateSelected -= OnDateSelected;
|
|
_currentPicker.OnDateSelected -= OnDateTimeSelected;
|
|
_currentPicker.OnClosed -= OnPickerClosed;
|
|
_currentPicker = null;
|
|
}
|
|
}
|
|
|
|
private void SetDate(DateTime date)
|
|
{
|
|
_selectedDate = date;
|
|
_selectedDateTime = new DateTime(date.Year, date.Month, date.Day,
|
|
_selectedDateTime.Hour, _selectedDateTime.Minute, 0);
|
|
|
|
if (_dateLabel != null)
|
|
{
|
|
_dateLabel.text = FormatDate(_selectedDate);
|
|
}
|
|
|
|
if (_dateTimeLabel != null)
|
|
{
|
|
_dateTimeLabel.text = FormatDateTime(_selectedDateTime);
|
|
}
|
|
|
|
Debug.Log($"Preset Date Set: {FormatDate(date)}");
|
|
}
|
|
|
|
private string FormatDate(DateTime date)
|
|
{
|
|
return date.ToString("yyyy-MM-dd");
|
|
}
|
|
|
|
private string FormatDateTime(DateTime dateTime)
|
|
{
|
|
return dateTime.ToString("yyyy-MM-dd HH:mm");
|
|
}
|
|
|
|
private string FormatDateRange(DateTime start, DateTime end)
|
|
{
|
|
return $"{start:yyyy-MM-dd} ~ {end:yyyy-MM-dd}";
|
|
}
|
|
|
|
private void OpenDateRangePicker()
|
|
{
|
|
if (_root == null || _currentPicker != null) return;
|
|
|
|
_currentPicker = UTKDatePicker.ShowRange(
|
|
_rangeStartDate,
|
|
_rangeEndDate,
|
|
false,
|
|
"Select Date Range"
|
|
);
|
|
|
|
_currentPicker.OnDateRangeSelected += OnDateRangeSelected;
|
|
_currentPicker.OnClosed += OnPickerClosed;
|
|
}
|
|
|
|
private async UniTaskVoid OpenDateRangePickerAsync()
|
|
{
|
|
if (_root == null) return;
|
|
|
|
// ShowRangeAsync를 사용하여 날짜 범위 선택 대기
|
|
// OK 클릭 시 선택된 범위 반환, 취소/닫기 시 null 반환
|
|
var result = await UTKDatePicker.ShowRangeAsync(
|
|
_rangeStartDate,
|
|
_rangeEndDate,
|
|
false,
|
|
"Select Date Range (Async)"
|
|
);
|
|
|
|
if (result.HasValue)
|
|
{
|
|
_rangeStartDate = result.Value.Start;
|
|
_rangeEndDate = result.Value.End;
|
|
if (_dateRangeLabel != null)
|
|
{
|
|
_dateRangeLabel.text = FormatDateRange(result.Value.Start, result.Value.End);
|
|
}
|
|
Debug.Log($"[Async] Range Result: {FormatDateRange(result.Value.Start, result.Value.End)}");
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("[Async] Date range selection cancelled");
|
|
}
|
|
}
|
|
|
|
private void OnDateRangeSelected(DateTime start, DateTime end)
|
|
{
|
|
_rangeStartDate = start;
|
|
_rangeEndDate = end;
|
|
if (_dateRangeLabel != null)
|
|
{
|
|
_dateRangeLabel.text = FormatDateRange(start, end);
|
|
}
|
|
Debug.Log($"Date Range Selected: {FormatDateRange(start, end)}");
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (_currentPicker != null)
|
|
{
|
|
_currentPicker.OnDateSelected -= OnDateSelected;
|
|
_currentPicker.OnDateSelected -= OnDateTimeSelected;
|
|
_currentPicker.OnDateRangeSelected -= OnDateRangeSelected;
|
|
_currentPicker.OnClosed -= OnPickerClosed;
|
|
_currentPicker.Dispose();
|
|
_currentPicker = null;
|
|
}
|
|
}
|
|
}
|
|
}
|