스타일 가이드 적용 완료. UTKCOlorPicker, UTKDatePicker 확인해야 함

This commit is contained in:
logonkhi
2026-01-12 20:16:17 +09:00
parent 6ae48ff30e
commit e1f2ac5b02
31 changed files with 1854 additions and 660 deletions

View File

@@ -1,5 +1,6 @@
#nullable enable
using System;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UIToolkit.Modal;
@@ -105,7 +106,7 @@ namespace UVC.Sample.UIToolkit
alphaRow.style.marginBottom = 15;
_useAlphaToggle = new Toggle("Use Alpha Channel");
_useAlphaToggle.value = false;
_useAlphaToggle.value = true;
_useAlphaToggle.style.color = Color.white;
alphaRow.Add(_useAlphaToggle);
@@ -117,6 +118,12 @@ namespace UVC.Sample.UIToolkit
openPickerBtn.style.marginBottom = 10;
container.Add(openPickerBtn);
// Async 버튼
var openPickerAsyncBtn = new Button(() => OpenColorPickerAsync().Forget()) { text = "Open Color Picker (Async)" };
openPickerAsyncBtn.style.height = 32;
openPickerAsyncBtn.style.marginBottom = 10;
container.Add(openPickerAsyncBtn);
// 프리셋 색상 버튼들
var presetLabel = new Label("Preset Colors:");
presetLabel.style.color = Color.white;
@@ -162,6 +169,30 @@ namespace UVC.Sample.UIToolkit
_currentPicker.OnColorSelected += OnColorSelected;
}
private async UniTaskVoid OpenColorPickerAsync()
{
if (_root == null) return;
bool useAlpha = _useAlphaToggle?.value ?? true;
// ShowAsync를 사용하여 색상 선택 대기
// OK 클릭 시 선택된 색상 반환, 취소/닫기 시 _currentColor 반환
Color selectedColor = await UTKColorPicker.ShowAsync(_root, _currentColor, "Select Color (Async)", useAlpha);
// 결과 처리
_currentColor = selectedColor;
if (_colorPreview != null)
{
_colorPreview.style.backgroundColor = selectedColor;
}
if (_colorLabel != null)
{
_colorLabel.text = ColorToHex(selectedColor);
}
Debug.Log($"[Async] Color Result: {ColorToHex(selectedColor)}");
}
private void OnColorChanged(Color color)
{
// 실시간 미리보기 업데이트

View File

@@ -1,5 +1,6 @@
#nullable enable
using System;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.Locale;
@@ -18,9 +19,12 @@ namespace UVC.Sample.UIToolkit
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()
@@ -78,6 +82,44 @@ namespace UVC.Sample.UIToolkit
_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;
@@ -185,6 +227,34 @@ namespace UVC.Sample.UIToolkit
_currentPicker.OnClosed += OnPickerClosed;
}
private async UniTaskVoid OpenDatePickerAsync()
{
if (_root == null) return;
// ShowAsync를 사용하여 날짜 선택 대기
// OK 클릭 시 선택된 날짜 반환, 취소/닫기 시 null 반환
DateTime? result = await UTKDatePicker.ShowAsync(
_root,
_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;
@@ -245,12 +315,75 @@ namespace UVC.Sample.UIToolkit
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(
_root,
_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(
_root,
_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;

View File

@@ -1,6 +1,7 @@
#nullable enable
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UIToolkit;
@@ -787,6 +788,21 @@ public class UTKStyleGuideSample : MonoBehaviour
}),
}),
new TreeViewItemData<string>(9, "Parent 3"),
new TreeViewItemData<string>(10, "Parent 4", new List<TreeViewItemData<string>>
{
new TreeViewItemData<string>(11, "Child 4-1"),
new TreeViewItemData<string>(12, "Child 4-2"),
}),
new TreeViewItemData<string>(13, "Parent 5", new List<TreeViewItemData<string>>
{
new TreeViewItemData<string>(14, "Child 5-1"),
new TreeViewItemData<string>(15, "Child 5-2", new List<TreeViewItemData<string>>
{
new TreeViewItemData<string>(16, "Grandchild 5-2-1"),
new TreeViewItemData<string>(17, "Grandchild 5-2-2"),
}),
}),
new TreeViewItemData<string>(18, "Parent 6"),
};
treeView.SetRootItems(treeItems);
@@ -794,31 +810,138 @@ public class UTKStyleGuideSample : MonoBehaviour
container.Add(treeView);
}
/// <summary>
/// MultiColumnListView 샘플 데이터 클래스
/// </summary>
private class SampleListItem
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Status { get; set; } = "";
public int Progress { get; set; }
}
private void CreateMultiColumnListViewPreview(VisualElement container)
{
AddDescription(container, "멀티 컬럼 리스트 뷰 (정렬 가능한 테이블)");
var placeholder = new Label("MultiColumnListView requires Columns and data binding setup.");
placeholder.style.color = new Color(0.6f, 0.6f, 0.6f);
container.Add(placeholder);
var listView = new UTKMultiColumnListView();
listView.style.height = 200;
listView.style.width = 400;
listView.style.width = 450;
// 컬럼 정의
listView.columns.Add(new Column { name = "id", title = "ID", width = 50 });
listView.columns.Add(new Column { name = "name", title = "Name", width = 150, stretchable = true });
listView.columns.Add(new Column { name = "status", title = "Status", width = 100 });
listView.columns.Add(new Column { name = "progress", title = "Progress", width = 80 });
// 샘플 데이터
var items = new List<SampleListItem>
{
new() { Id = 1, Name = "Task Alpha", Status = "Active", Progress = 75 },
new() { Id = 2, Name = "Task Beta", Status = "Pending", Progress = 30 },
new() { Id = 3, Name = "Task Gamma", Status = "Completed", Progress = 100 },
new() { Id = 4, Name = "Task Delta", Status = "Active", Progress = 50 },
new() { Id = 5, Name = "Task Epsilon", Status = "Cancelled", Progress = 0 },
new() { Id = 6, Name = "Task Zeta", Status = "Active", Progress = 90 },
new() { Id = 7, Name = "Task Eta", Status = "Pending", Progress = 15 },
new() { Id = 8, Name = "Task Theta", Status = "Completed", Progress = 100 },
};
listView.itemsSource = items;
listView.fixedItemHeight = 24;
// 셀 생성 및 바인딩
listView.columns["id"].makeCell = () => new Label();
listView.columns["id"].bindCell = (e, i) => ((Label)e).text = items[i].Id.ToString();
listView.columns["name"].makeCell = () => new Label();
listView.columns["name"].bindCell = (e, i) => ((Label)e).text = items[i].Name;
listView.columns["status"].makeCell = () => new Label();
listView.columns["status"].bindCell = (e, i) => ((Label)e).text = items[i].Status;
listView.columns["progress"].makeCell = () => new Label();
listView.columns["progress"].bindCell = (e, i) => ((Label)e).text = $"{items[i].Progress}%";
container.Add(listView);
}
/// <summary>
/// MultiColumnTreeView 샘플 데이터 클래스
/// </summary>
private class SampleTreeItem
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Type { get; set; } = "";
public string Size { get; set; } = "";
}
private void CreateMultiColumnTreeViewPreview(VisualElement container)
{
AddDescription(container, "멀티 컬럼 트리 뷰 (계층적 테이블)");
var placeholder = new Label("MultiColumnTreeView requires Columns and TreeViewItemData setup.");
placeholder.style.color = new Color(0.6f, 0.6f, 0.6f);
container.Add(placeholder);
var treeView = new UTKMultiColumnTreeView();
treeView.style.height = 200;
treeView.style.width = 400;
treeView.style.height = 220;
treeView.style.width = 450;
// 컬럼 정의
treeView.columns.Add(new Column { name = "name", title = "Name", width = 200, stretchable = true });
treeView.columns.Add(new Column { name = "type", title = "Type", width = 100 });
treeView.columns.Add(new Column { name = "size", title = "Size", width = 80 });
// 샘플 데이터 (계층 구조)
var rootItems = new List<TreeViewItemData<SampleTreeItem>>
{
new(1, new SampleTreeItem { Id = 1, Name = "Documents", Type = "Folder", Size = "2.5 GB" },
new List<TreeViewItemData<SampleTreeItem>>
{
new(11, new SampleTreeItem { Id = 11, Name = "Reports", Type = "Folder", Size = "500 MB" },
new List<TreeViewItemData<SampleTreeItem>>
{
new(111, new SampleTreeItem { Id = 111, Name = "Q1_Report.pdf", Type = "PDF", Size = "2.3 MB" }),
new(112, new SampleTreeItem { Id = 112, Name = "Q2_Report.pdf", Type = "PDF", Size = "1.8 MB" }),
}),
new(12, new SampleTreeItem { Id = 12, Name = "Images", Type = "Folder", Size = "1.2 GB" }),
}),
new(2, new SampleTreeItem { Id = 2, Name = "Projects", Type = "Folder", Size = "5.0 GB" },
new List<TreeViewItemData<SampleTreeItem>>
{
new(21, new SampleTreeItem { Id = 21, Name = "ProjectA", Type = "Folder", Size = "2.0 GB" }),
new(22, new SampleTreeItem { Id = 22, Name = "ProjectB", Type = "Folder", Size = "3.0 GB" }),
}),
new(3, new SampleTreeItem { Id = 3, Name = "Config.json", Type = "JSON", Size = "4 KB" }),
};
treeView.SetRootItems(rootItems);
treeView.fixedItemHeight = 22;
// 셀 생성 및 바인딩
treeView.columns["name"].makeCell = () => new Label();
treeView.columns["name"].bindCell = (e, i) =>
{
var item = treeView.GetItemDataForIndex<SampleTreeItem>(i);
((Label)e).text = item.Name;
};
treeView.columns["type"].makeCell = () => new Label();
treeView.columns["type"].bindCell = (e, i) =>
{
var item = treeView.GetItemDataForIndex<SampleTreeItem>(i);
((Label)e).text = item.Type;
};
treeView.columns["size"].makeCell = () => new Label();
treeView.columns["size"].bindCell = (e, i) =>
{
var item = treeView.GetItemDataForIndex<SampleTreeItem>(i);
((Label)e).text = item.Size;
};
// 기본 확장
treeView.ExpandAll();
container.Add(treeView);
}
@@ -840,16 +963,50 @@ public class UTKStyleGuideSample : MonoBehaviour
{
AddDescription(container, "스크롤 뷰 컴포넌트");
var scrollView = new UTKScrollView();
scrollView.style.height = 150;
scrollView.style.width = 300;
var row = CreateRow(container, "ScrollViews");
// 세로 스크롤
var verticalScroll = new UTKScrollView();
verticalScroll.style.height = 150;
verticalScroll.style.width = 200;
for (int i = 1; i <= 15; i++)
{
scrollView.Add(new Label($"Scrollable Item {i}"));
verticalScroll.Add(new Label($"Vertical Item {i}"));
}
row.Add(verticalScroll);
container.Add(scrollView);
// 가로 스크롤
var horizontalScroll = new UTKScrollView();
horizontalScroll.mode = ScrollViewMode.Horizontal;
horizontalScroll.style.height = 150;
horizontalScroll.style.width = 200;
var horizontalContent = new VisualElement();
horizontalContent.style.flexDirection = FlexDirection.Row;
for (int i = 1; i <= 15; i++)
{
var item = new Label($"H-Item {i}");
item.style.minWidth = 80;
item.style.marginRight = 8;
horizontalContent.Add(item);
}
horizontalScroll.Add(horizontalContent);
row.Add(horizontalScroll);
// 양방향 스크롤
var bothScroll = new UTKScrollView();
bothScroll.mode = ScrollViewMode.VerticalAndHorizontal;
bothScroll.style.height = 150;
bothScroll.style.width = 200;
for (int i = 1; i <= 10; i++)
{
var item = new Label($"This is a very long scrollable item number {i} that requires horizontal scrolling");
item.style.whiteSpace = WhiteSpace.NoWrap;
bothScroll.Add(item);
}
row.Add(bothScroll);
}
#endregion
@@ -909,23 +1066,102 @@ public class UTKStyleGuideSample : MonoBehaviour
{
if (_root == null) return;
AddDescription(container, "알림 다이얼로그");
AddDescription(container, "알림 다이얼로그 (async/await 지원)");
var row = CreateRow(container, "Alerts");
// Alert Types (Async)
var row1 = CreateRow(container, "Alert Types (Async)");
var infoBtn = new UTKButton("Show Info", "", UTKButton.ButtonVariant.Primary);
infoBtn.OnClicked += () => UTKAlert.ShowInfo(_root, "Information", "This is an info message.");
row.Add(infoBtn);
UTKAlert.SetRoot(_root);
var warnBtn = new UTKButton("Show Warning", "", UTKButton.ButtonVariant.Normal);
warnBtn.OnClicked += () => UTKAlert.ShowWarning(_root, "Warning", "This is a warning message.");
row.Add(warnBtn);
var infoBtn = new UTKButton("Info", "", UTKButton.ButtonVariant.Primary);
infoBtn.OnClicked += () => ShowInfoAlertAsync().Forget();
row1.Add(infoBtn);
var confirmBtn = new UTKButton("Show Confirm", "", UTKButton.ButtonVariant.Normal);
confirmBtn.OnClicked += () => UTKAlert.ShowConfirm(_root, "Confirm", "Are you sure?",
() => Debug.Log("Confirmed!"),
() => Debug.Log("Cancelled!"));
row.Add(confirmBtn);
var successBtn = new UTKButton("Success", "", UTKButton.ButtonVariant.Normal);
successBtn.OnClicked += () => ShowSuccessAlertAsync().Forget();
row1.Add(successBtn);
var warnBtn = new UTKButton("Warning", "", UTKButton.ButtonVariant.Normal);
warnBtn.OnClicked += () => ShowWarningAlertAsync().Forget();
row1.Add(warnBtn);
var errorBtn = new UTKButton("Error", "", UTKButton.ButtonVariant.Danger);
errorBtn.OnClicked += () => ShowErrorAlertAsync().Forget();
row1.Add(errorBtn);
// Confirm Dialog (Async)
var row2 = CreateRow(container, "Confirm Dialog (Async)");
var confirmBtn = new UTKButton("Confirm", "", UTKButton.ButtonVariant.Normal);
confirmBtn.OnClicked += () => ShowConfirmAlertAsync().Forget();
row2.Add(confirmBtn);
var confirmCustomBtn = new UTKButton("Custom Labels", "", UTKButton.ButtonVariant.Normal);
confirmCustomBtn.OnClicked += () => ShowConfirmCustomLabelsAsync().Forget();
row2.Add(confirmCustomBtn);
// Callback Style (Non-Async)
var row3 = CreateRow(container, "Callback Style");
var callbackBtn = new UTKButton("With Callback", "", UTKButton.ButtonVariant.OutlineNormal);
callbackBtn.OnClicked += () =>
{
UTKAlert.ShowInfo(_root, "Callback Style", "This uses callback instead of async.",
onClose: () => Debug.Log("Alert closed via callback"));
};
row3.Add(callbackBtn);
var confirmCallbackBtn = new UTKButton("Confirm Callback", "", UTKButton.ButtonVariant.OutlineNormal);
confirmCallbackBtn.OnClicked += () =>
{
UTKAlert.ShowConfirm(_root, "Confirm", "Do you want to proceed?",
onConfirm: () => Debug.Log("Confirmed via callback!"),
onCancel: () => Debug.Log("Cancelled via callback!"));
};
row3.Add(confirmCallbackBtn);
}
private async UniTaskVoid ShowInfoAlertAsync()
{
if (_root == null) return;
await UTKAlert.ShowInfoAsync("Information", "This is an info message.");
Debug.Log("Info alert closed");
}
private async UniTaskVoid ShowSuccessAlertAsync()
{
if (_root == null) return;
await UTKAlert.ShowSuccessAsync("Success", "Operation completed successfully!", closeOnBlockerClick: true);
Debug.Log("Success alert closed");
}
private async UniTaskVoid ShowWarningAlertAsync()
{
if (_root == null) return;
await UTKAlert.ShowWarningAsync("Warning", "This is a warning message.");
Debug.Log("Warning alert closed");
}
private async UniTaskVoid ShowErrorAlertAsync()
{
if (_root == null) return;
await UTKAlert.ShowErrorAsync("Error", "An error has occurred!");
Debug.Log("Error alert closed");
}
private async UniTaskVoid ShowConfirmAlertAsync()
{
if (_root == null) return;
bool result = await UTKAlert.ShowConfirmAsync("Confirm", "Are you sure?");
Debug.Log(result ? "Confirmed!" : "Cancelled!");
}
private async UniTaskVoid ShowConfirmCustomLabelsAsync()
{
if (_root == null) return;
bool result = await UTKAlert.ShowConfirmAsync("Delete Item", "Are you sure you want to delete this item?",
confirmLabel: "Delete", cancelLabel: "Keep");
Debug.Log(result ? "Item deleted!" : "Item kept!");
}
private void CreateToastPreview(VisualElement container)
@@ -936,16 +1172,22 @@ public class UTKStyleGuideSample : MonoBehaviour
var row = CreateRow(container, "Toasts");
UTKToast.SetRoot(_root);
var infoBtn = new UTKButton("Info Toast", "", UTKButton.ButtonVariant.Primary);
infoBtn.OnClicked += () => UTKToast.ShowInfo(_root, "This is an info toast!", 3000);
infoBtn.OnClicked += () => UTKToast.Show("This is an info toast!This is an info toast!This is an info toast!This is an info toast!This is an info toast!");
row.Add(infoBtn);
var successBtn = new UTKButton("Success Toast", "", UTKButton.ButtonVariant.Normal);
successBtn.OnClicked += () => UTKToast.ShowSuccess(_root, "Operation successful!", 3000);
successBtn.OnClicked += () => UTKToast.ShowSuccess("Operation successful!");
row.Add(successBtn);
var warningBtn = new UTKButton("Warning Toast", "", UTKButton.ButtonVariant.Normal);
warningBtn.OnClicked += () => UTKToast.ShowWarning("Warning: Check your input!");
row.Add(warningBtn);
var errorBtn = new UTKButton("Error Toast", "", UTKButton.ButtonVariant.Danger);
errorBtn.OnClicked += () => UTKToast.ShowError(_root, "An error occurred!", 3000);
errorBtn.OnClicked += () => UTKToast.ShowError("An error occurred!");
row.Add(errorBtn);
}
@@ -968,37 +1210,227 @@ public class UTKStyleGuideSample : MonoBehaviour
#region Picker Previews
private Color _selectedColor = Color.white;
private VisualElement? _colorPreviewBox;
private Label? _colorHexLabel;
private void CreateColorPickerPreview(VisualElement container)
{
AddDescription(container, "색상 선택 컴포넌트");
if (_root == null) return;
var colorLabel = new Label("Selected: #FFFFFFFF");
container.Add(colorLabel);
AddDescription(container, "색상 선택 컴포넌트 (버튼 클릭으로 모달 표시)");
var colorPicker = new UTKColorPicker();
colorPicker.style.position = Position.Relative;
colorPicker.SetColor(Color.white);
colorPicker.OnColorChanged += (color) =>
{
colorLabel.text = $"Selected: #{ColorUtility.ToHtmlStringRGBA(color)}";
};
container.Add(colorPicker);
// 현재 색상 미리보기
var previewRow = CreateRow(container, "Current Color");
_colorPreviewBox = new VisualElement();
_colorPreviewBox.style.width = 60;
_colorPreviewBox.style.height = 30;
_colorPreviewBox.style.backgroundColor = _selectedColor;
_colorPreviewBox.style.borderTopLeftRadius = 4;
_colorPreviewBox.style.borderTopRightRadius = 4;
_colorPreviewBox.style.borderBottomLeftRadius = 4;
_colorPreviewBox.style.borderBottomRightRadius = 4;
_colorPreviewBox.style.borderTopWidth = 1;
_colorPreviewBox.style.borderBottomWidth = 1;
_colorPreviewBox.style.borderLeftWidth = 1;
_colorPreviewBox.style.borderRightWidth = 1;
_colorPreviewBox.style.borderTopColor = new Color(0.4f, 0.4f, 0.4f);
_colorPreviewBox.style.borderBottomColor = new Color(0.4f, 0.4f, 0.4f);
_colorPreviewBox.style.borderLeftColor = new Color(0.4f, 0.4f, 0.4f);
_colorPreviewBox.style.borderRightColor = new Color(0.4f, 0.4f, 0.4f);
previewRow.Add(_colorPreviewBox);
_colorHexLabel = new Label($"#{ColorUtility.ToHtmlStringRGBA(_selectedColor)}");
_colorHexLabel.style.marginLeft = 10;
previewRow.Add(_colorHexLabel);
// 버튼들
var row1 = CreateRow(container, "With Alpha");
var withAlphaBtn = new UTKButton("Open Color Picker (Alpha)", "", UTKButton.ButtonVariant.Primary);
withAlphaBtn.OnClicked += () => OpenColorPicker(true);
row1.Add(withAlphaBtn);
var row2 = CreateRow(container, "Without Alpha");
var withoutAlphaBtn = new UTKButton("Open Color Picker (No Alpha)", "", UTKButton.ButtonVariant.Normal);
withoutAlphaBtn.OnClicked += () => OpenColorPicker(false);
row2.Add(withoutAlphaBtn);
// Async 버튼
var row3 = CreateRow(container, "Async/Await");
var asyncBtn = new UTKButton("Open Color Picker (Async)", "", UTKButton.ButtonVariant.Normal);
asyncBtn.OnClicked += () => OpenColorPickerAsync().Forget();
row3.Add(asyncBtn);
}
private void OpenColorPicker(bool useAlpha)
{
if (_root == null) return;
var picker = UTKColorPicker.Show(_root, _selectedColor, "Select Color", useAlpha);
picker.OnColorChanged += (color) =>
{
// 실시간 미리보기 업데이트
if (_colorPreviewBox != null)
_colorPreviewBox.style.backgroundColor = color;
if (_colorHexLabel != null)
_colorHexLabel.text = useAlpha
? $"#{ColorUtility.ToHtmlStringRGBA(color)}"
: $"#{ColorUtility.ToHtmlStringRGB(color)}";
};
picker.OnColorSelected += (color) =>
{
_selectedColor = color;
Debug.Log($"Color Selected: #{(useAlpha ? ColorUtility.ToHtmlStringRGBA(color) : ColorUtility.ToHtmlStringRGB(color))}");
};
}
private async UniTaskVoid OpenColorPickerAsync()
{
if (_root == null) return;
// ShowAsync를 사용하여 색상 선택 대기
// OK 클릭 시 선택된 색상 반환, 취소/닫기 시 _selectedColor 반환
Color result = await UTKColorPicker.ShowAsync(_root, _selectedColor, "Select Color (Async)", useAlpha: true);
// 결과 처리
_selectedColor = result;
if (_colorPreviewBox != null)
_colorPreviewBox.style.backgroundColor = result;
if (_colorHexLabel != null)
_colorHexLabel.text = $"#{ColorUtility.ToHtmlStringRGBA(result)}";
Debug.Log($"[Async] Color Result: #{ColorUtility.ToHtmlStringRGBA(result)}");
}
private DateTime _selectedDate = DateTime.Today;
private DateTime _rangeStartDate = DateTime.Today;
private DateTime _rangeEndDate = DateTime.Today.AddDays(7);
private Label? _dateLabel;
private Label? _rangeDateLabel;
private void CreateDatePickerPreview(VisualElement container)
{
AddDescription(container, "날짜 선택 컴포넌트");
if (_root == null) return;
var dateLabel = new Label($"Selected: {DateTime.Now:yyyy-MM-dd}");
container.Add(dateLabel);
AddDescription(container, "날짜 선택 컴포넌트 (버튼 클릭으로 모달 표시)");
var datePicker = new UTKDatePicker();
datePicker.style.position = Position.Relative;
datePicker.OnDateSelected += (date) =>
// 현재 선택된 날짜 표시
var previewRow = CreateRow(container, "Current Date");
_dateLabel = new Label($"Selected: {_selectedDate:yyyy-MM-dd}");
previewRow.Add(_dateLabel);
// 날짜만 선택 버튼
var row1 = CreateRow(container, "Date Only");
var dateOnlyBtn = new UTKButton("Open Date Picker", "", UTKButton.ButtonVariant.Primary);
dateOnlyBtn.OnClicked += () => OpenDatePicker(UTKDatePicker.PickerMode.DateOnly);
row1.Add(dateOnlyBtn);
// 날짜 + 시간 선택 버튼
var row2 = CreateRow(container, "Date & Time");
var dateTimeBtn = new UTKButton("Open DateTime Picker", "", UTKButton.ButtonVariant.Normal);
dateTimeBtn.OnClicked += () => OpenDatePicker(UTKDatePicker.PickerMode.DateAndTime);
row2.Add(dateTimeBtn);
// Async 버튼
var row3 = CreateRow(container, "Async/Await");
var asyncBtn = new UTKButton("Open Date Picker (Async)", "", UTKButton.ButtonVariant.Normal);
asyncBtn.OnClicked += () => OpenDatePickerAsync().Forget();
row3.Add(asyncBtn);
// 날짜 범위 표시
var rangePreviewRow = CreateRow(container, "Date Range");
_rangeDateLabel = new Label($"Range: {_rangeStartDate:yyyy-MM-dd} ~ {_rangeEndDate:yyyy-MM-dd}");
rangePreviewRow.Add(_rangeDateLabel);
// 날짜 범위 선택 버튼
var row4 = CreateRow(container, "Date Range");
var rangeBtn = new UTKButton("Open Range Picker", "", UTKButton.ButtonVariant.Normal);
rangeBtn.OnClicked += OpenDateRangePicker;
row4.Add(rangeBtn);
// 날짜 범위 Async 버튼
var row5 = CreateRow(container, "Range Async");
var rangeAsyncBtn = new UTKButton("Open Range Picker (Async)", "", UTKButton.ButtonVariant.Normal);
rangeAsyncBtn.OnClicked += () => OpenDateRangePickerAsync().Forget();
row5.Add(rangeAsyncBtn);
}
private void OpenDatePicker(UTKDatePicker.PickerMode mode)
{
if (_root == null) return;
string title = mode == UTKDatePicker.PickerMode.DateOnly ? "Select Date" : "Select Date & Time";
var picker = UTKDatePicker.Show(_root, _selectedDate, mode, title);
picker.OnDateSelected += (date) =>
{
dateLabel.text = $"Selected: {date:yyyy-MM-dd HH:mm}";
_selectedDate = date;
if (_dateLabel != null)
{
_dateLabel.text = mode == UTKDatePicker.PickerMode.DateOnly
? $"Selected: {date:yyyy-MM-dd}"
: $"Selected: {date:yyyy-MM-dd HH:mm}";
}
Debug.Log($"Date Selected: {date:yyyy-MM-dd HH:mm}");
};
container.Add(datePicker);
}
private async UniTaskVoid OpenDatePickerAsync()
{
if (_root == null) return;
// ShowAsync를 사용하여 날짜 선택 대기
// OK 클릭 시 선택된 날짜 반환, 취소/닫기 시 null 반환
DateTime? result = await UTKDatePicker.ShowAsync(_root, _selectedDate, UTKDatePicker.PickerMode.DateOnly, "Select Date (Async)");
if (result.HasValue)
{
_selectedDate = result.Value;
if (_dateLabel != null)
_dateLabel.text = $"Selected: {result.Value:yyyy-MM-dd}";
Debug.Log($"[Async] Date Result: {result.Value:yyyy-MM-dd}");
}
else
{
Debug.Log("[Async] Date selection cancelled");
}
}
private void OpenDateRangePicker()
{
if (_root == null) return;
var picker = UTKDatePicker.ShowRange(_root, _rangeStartDate, _rangeEndDate, false, "Select Date Range");
picker.OnDateRangeSelected += (start, end) =>
{
_rangeStartDate = start;
_rangeEndDate = end;
if (_rangeDateLabel != null)
_rangeDateLabel.text = $"Range: {start:yyyy-MM-dd} ~ {end:yyyy-MM-dd}";
Debug.Log($"Date Range Selected: {start:yyyy-MM-dd} ~ {end:yyyy-MM-dd}");
};
}
private async UniTaskVoid OpenDateRangePickerAsync()
{
if (_root == null) return;
// ShowRangeAsync를 사용하여 날짜 범위 선택 대기
// OK 클릭 시 선택된 범위 반환, 취소/닫기 시 null 반환
var result = await UTKDatePicker.ShowRangeAsync(_root, _rangeStartDate, _rangeEndDate, false, "Select Date Range (Async)");
if (result.HasValue)
{
_rangeStartDate = result.Value.Start;
_rangeEndDate = result.Value.End;
if (_rangeDateLabel != null)
_rangeDateLabel.text = $"Range: {result.Value.Start:yyyy-MM-dd} ~ {result.Value.End:yyyy-MM-dd}";
Debug.Log($"[Async] Range Result: {result.Value.Start:yyyy-MM-dd} ~ {result.Value.End:yyyy-MM-dd}");
}
else
{
Debug.Log("[Async] Date range selection cancelled");
}
}
#endregion