#nullable enable using System; using System.Collections.Generic; using System.Linq; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UIElements; using UVC.UIToolkit; /// /// UTK 컴포넌트들의 테마 전환 테스트를 위한 샘플입니다. /// 왼쪽에 컨트롤 목록, 오른쪽에 선택된 컨트롤 미리보기를 표시합니다. /// UXML 파일을 로드하여 각 컴포넌트 샘플을 표시합니다. /// public partial class UTKStyleGuideSample : MonoBehaviour { [SerializeField] public UIDocument? uiDocument; [SerializeField] [Tooltip("시작 시 적용할 테마")] private UTKTheme initialTheme = UTKTheme.Dark; #region Constants private static class UssClasses { public const string Main = "utk-sample-main"; public const string Header = "utk-sample-header"; public const string Title = "utk-sample-title"; public const string ThemeArea = "utk-sample-theme-area"; public const string ThemeLabel = "utk-sample-theme-label"; public const string Content = "utk-sample-content"; public const string Sidebar = "utk-sample-sidebar"; public const string SidebarScroll = "utk-sample-sidebar-scroll"; public const string Preview = "utk-sample-preview"; public const string PreviewScroll = "utk-sample-preview-scroll"; public const string PreviewTitle = "utk-sample-preview-title"; public const string PreviewContent = "utk-sample-preview-content"; public const string ControlItem = "utk-sample-control-item"; public const string ControlItemSelected = "utk-sample-control-item--selected"; } /// /// 컨트롤 이름과 UXML 경로 매핑 /// private static readonly Dictionary ControlUxmlPaths = new() { // Icon ["UTKMaterialIcons"] = "UIToolkit/Sample/Icon/UTKMaterialIconsSample", ["UTKImageIcons"] = "UIToolkit/Sample/Icon/UTKImageIconsSample", ["UTKImage"] = "UIToolkit/Sample/Icon/UTKImageSample", // Button ["UTKButton"] = "UIToolkit/Sample/Button/UTKButtonSample", ["UTKCheckBox"] = "UIToolkit/Sample/Button/UTKCheckBoxSample", ["UTKToggle"] = "UIToolkit/Sample/Button/UTKToggleSample", ["UTKRadioButton"] = "UIToolkit/Sample/Button/UTKRadioButtonSample", ["UTKToggleButtonGroup"] = "UIToolkit/Sample/Button/UTKToggleButtonGroupSample", ["UTKImageToggleButton"] = "UIToolkit/Sample/Button/UTKImageToggleButtonSample", // Input ["UTKInputField"] = "UIToolkit/Sample/Input/UTKInputFieldSample", ["UTKIntegerField"] = "UIToolkit/Sample/Input/UTKIntegerFieldSample", ["UTKLongField"] = "UIToolkit/Sample/Input/UTKLongFieldSample", ["UTKFloatField"] = "UIToolkit/Sample/Input/UTKFloatFieldSample", ["UTKDoubleField"] = "UIToolkit/Sample/Input/UTKDoubleFieldSample", ["UTKVector2Field"] = "UIToolkit/Sample/Input/UTKVector2FieldSample", ["UTKVector3Field"] = "UIToolkit/Sample/Input/UTKVector3FieldSample", ["UTKVector4Field"] = "UIToolkit/Sample/Input/UTKVector4FieldSample", ["UTKRectField"] = "UIToolkit/Sample/Input/UTKRectFieldSample", ["UTKBoundsField"] = "UIToolkit/Sample/Input/UTKBoundsFieldSample", ["UTKIntStepper"] = "UIToolkit/Sample/Input/UTKIntStepperSample", ["UTKFloatStepper"] = "UIToolkit/Sample/Input/UTKFloatStepperSample", // Slider ["UTKSlider"] = "UIToolkit/Sample/Slider/UTKSliderSample", ["UTKSliderInt"] = "UIToolkit/Sample/Slider/UTKSliderIntSample", ["UTKMinMaxSlider"] = "UIToolkit/Sample/Slider/UTKMinMaxSliderSample", ["UTKProgressBar"] = "UIToolkit/Sample/Slider/UTKProgressBarSample", // Dropdown ["UTKDropdown"] = "UIToolkit/Sample/Dropdown/UTKDropdownSample", ["UTKEnumDropDown"] = "UIToolkit/Sample/Dropdown/UTKEnumDropDownSample", ["UTKMultiSelectDropdown"] = "UIToolkit/Sample/Dropdown/UTKMultiSelectDropdownSample", ["UTKButtonDropdown"] = "UIToolkit/Sample/Dropdown/UTKButtonDropdownSample", // Label ["UTKLabel"] = "UIToolkit/Sample/Label/UTKLabelSample", ["UTKHelpBox"] = "UIToolkit/Sample/Label/UTKHelpBoxSample", // List ["UTKListView"] = "UIToolkit/Sample/List/UTKListViewSample", ["UTKTreeView"] = "UIToolkit/Sample/List/UTKTreeViewSample", ["UTKMultiColumnListView"] = "UIToolkit/Sample/List/UTKMultiColumnListViewSample", ["UTKMultiColumnTreeView"] = "UIToolkit/Sample/List/UTKMultiColumnTreeViewSample", ["UTKFoldout"] = "UIToolkit/Sample/List/UTKFoldoutSample", ["UTKScrollView"] = "UIToolkit/Sample/List/UTKScrollViewSample", ["UTKShortcutList"] = "UIToolkit/Sample/List/UTKShortcutListSample", ["UTKReordableList"] = "UIToolkit/Sample/List/UTKReordableListSample", ["UTKReordableTabList"] = "UIToolkit/Sample/List/UTKReordableTabListSample", // Card ["UTKCard"] = "UIToolkit/Sample/Card/UTKCardSample", ["UTKPanel"] = "UIToolkit/Sample/Card/UTKPanelSample", // Tab ["UTKTabView"] = "UIToolkit/Sample/Tab/UTKTabViewSample", // Modal ["UTKAlert"] = "UIToolkit/Sample/Modal/UTKAlertSample", ["UTKToast"] = "UIToolkit/Sample/Modal/UTKToastSample", ["UTKTooltip"] = "UIToolkit/Sample/Modal/UTKTooltipSample", ["UTKNotification"] = "UIToolkit/Sample/Modal/UTKNotificationSample", ["UTKModal"] = "UIToolkit/Sample/Modal/UTKModalSample", ["UTKLoading"] = "UIToolkit/Sample/Modal/UTKLoadingSample", // Picker ["UTKColorPicker"] = "UIToolkit/Sample/Picker/UTKColorPickerSample", ["UTKDatePicker"] = "UIToolkit/Sample/Picker/UTKDatePickerSample", // Menu ["UTKTopMenu"] = "UIToolkit/Sample/Menu/UTKTopMenuSample", // ToolBar ["UTKToolBar"] = "UIToolkit/Sample/ToolBar/UTKToolBarSample", // Window ["UTKAccordionListWindow"] = "UIToolkit/Sample/Window/UTKAccordionListWindowSample", ["UTKComponentListWindow"] = "UIToolkit/Sample/Window/UTKComponentListWindowSample", ["UTKComponentTabListWindow"] = "UIToolkit/Sample/Window/UTKComponentTabListWindowSample", ["UTKImageListWindow"] = "UIToolkit/Sample/Window/UTKImageListWindowSample", ["UTKTreeListWindow"] = "UIToolkit/Sample/Window/UTKTreeListWindowSample", ["UTKPropertyListWindow"] = "UIToolkit/Sample/Window/UTKPropertyListWindowSample", ["UTKSideBar"] = "UIToolkit/Sample/Window/UTKSideBarSample", }; private static readonly Dictionary ControlCategories = new() { ["Icon"] = new[] { "UTKMaterialIcons", "UTKImageIcons", "UTKImage" }, ["Button"] = new[] { "UTKButton", "UTKCheckBox", "UTKToggle", "UTKRadioButton", "UTKToggleButtonGroup", "UTKImageToggleButton" }, ["Input"] = new[] { "UTKInputField", "UTKIntegerField", "UTKLongField", "UTKFloatField", "UTKDoubleField", "UTKVector2Field", "UTKVector3Field", "UTKVector4Field", "UTKRectField", "UTKBoundsField", "UTKIntStepper", "UTKFloatStepper" }, ["Slider"] = new[] { "UTKSlider", "UTKSliderInt", "UTKMinMaxSlider", "UTKProgressBar" }, ["Dropdown"] = new[] { "UTKDropdown", "UTKEnumDropDown", "UTKMultiSelectDropdown", "UTKButtonDropdown" }, ["Label"] = new[] { "UTKLabel", "UTKHelpBox" }, ["List"] = new[] { "UTKListView", "UTKTreeView", "UTKMultiColumnListView", "UTKMultiColumnTreeView", "UTKFoldout", "UTKScrollView", "UTKShortcutList", "UTKReordableList", "UTKReordableTabList" }, ["Card"] = new[] { "UTKCard", "UTKPanel" }, ["Tab"] = new[] { "UTKTabView" }, ["Modal"] = new[] { "UTKAlert", "UTKToast", "UTKTooltip", "UTKNotification", "UTKModal", "UTKLoading" }, ["Picker"] = new[] { "UTKColorPicker", "UTKDatePicker" }, ["Menu"] = new[] { "UTKTopMenu" }, ["ToolBar"] = new[] { "UTKToolBar" }, ["Window"] = new[] { "UTKAccordionListWindow", "UTKComponentListWindow", "UTKComponentTabListWindow", "UTKImageListWindow", "UTKTreeListWindow", "UTKPropertyListWindow", "UTKSideBar" }, }; /// /// 컴포넌트별 코드 샘플 (C#, UXML, Icon) /// Initialize 메서드에서 SetCodeSamples를 호출하여 UXML의 UTKCodeBlock에 코드를 설정합니다. /// private static readonly Dictionary CodeSamples = new() { // 코드 샘플들은 각 컴포넌트의 Initialize 메서드에서 직접 정의됩니다. // 이 Dictionary는 더 이상 사용되지 않으며, 각 Initialize 메서드에서 직접 SetCodeSamples를 호출합니다. }; #endregion #region Fields private VisualElement? _root; private VisualElement? _previewContent; private Label? _previewTitle; private Label? _themeLabel; private string _selectedControl = ""; private VisualElement? _selectedItem; // UXML 캐시 private readonly Dictionary _uxmlCache = new(); // Picker 상태 private Color _selectedColor = Color.white; private VisualElement? _colorPreviewBox; private Label? _colorHexLabel; private DateTime _selectedDate = DateTime.Today; private DateTime _rangeStartDate = DateTime.Today; private DateTime _rangeEndDate = DateTime.Today.AddDays(7); private Label? _dateLabel; private Label? _rangeDateLabel; // Icon ListView private List? _iconNameList; private List? _filteredIconNameList; private ListView? _iconListView; private Label? _iconCountLabel; private List? _imageIconNameList; private List? _filteredImageIconNameList; private ListView? _imageIconListView; private Label? _imageIconCountLabel; private UTKCodeBlock? _materialIconCodeBlock; private UTKCodeBlock? _imageIconCodeBlock; private const int IconItemWidth = 80; private const int IconItemHeight = 80; private const int IconItemMargin = 4; private const int IconsPerRow = 10; private const int ImageIconItemWidth = 100; private const int ImageIconItemHeight = 100; private const int ImageIconItemMargin = 8; private const int ImageIconsPerRow = 8; #endregion #region Unity Lifecycle void Start() { uiDocument ??= GetComponent(); _root = uiDocument.rootVisualElement; UTKToast.SetRoot(_root); UTKThemeManager.Instance.RegisterRoot(_root); var sampleStyle = Resources.Load("UIToolkit/Sample/UTKStyleGuideSample"); if (sampleStyle != null) { _root.styleSheets.Add(sampleStyle); } UTKThemeManager.Instance.SetTheme(initialTheme); CreateUI(); } #endregion #region UI Creation private void CreateUI() { if (_root == null) return; var mainContainer = new VisualElement { name = "main-container" }; mainContainer.AddToClassList(UssClasses.Main); _root.Add(mainContainer); CreateHeader(mainContainer); var content = new VisualElement { name = "content" }; content.AddToClassList(UssClasses.Content); mainContainer.Add(content); CreateSidebar(content); CreatePreviewArea(content); SelectControl("UTKButton"); } private void CreateHeader(VisualElement parent) { var header = new VisualElement { name = "header" }; header.AddToClassList(UssClasses.Header); parent.Add(header); var title = new Label("UTK Style Guide"); title.AddToClassList(UssClasses.Title); header.Add(title); var themeArea = new VisualElement(); themeArea.AddToClassList(UssClasses.ThemeArea); header.Add(themeArea); _themeLabel = new Label($"Theme: {initialTheme}"); _themeLabel.AddToClassList(UssClasses.ThemeLabel); themeArea.Add(_themeLabel); var themeToggle = new UTKToggle("Dark Mode"); themeToggle.IsOn = initialTheme == UTKTheme.Dark; themeToggle.OnValueChanged += (isOn) => { var theme = isOn ? UTKTheme.Dark : UTKTheme.Light; UTKThemeManager.Instance.SetTheme(theme); if (_themeLabel != null) _themeLabel.text = $"Theme: {theme}"; }; themeArea.Add(themeToggle); } private void CreateSidebar(VisualElement parent) { var sidebar = new VisualElement { name = "sidebar" }; sidebar.AddToClassList(UssClasses.Sidebar); parent.Add(sidebar); var sidebarScroll = new ScrollView(ScrollViewMode.Vertical); sidebarScroll.AddToClassList(UssClasses.SidebarScroll); sidebar.Add(sidebarScroll); foreach (var category in ControlCategories) { var foldout = new UTKFoldout(category.Key, true); sidebarScroll.Add(foldout); foreach (var controlName in category.Value) { var item = new VisualElement { name = $"item-{controlName}" }; item.AddToClassList(UssClasses.ControlItem); var label = new Label(controlName); item.Add(label); var control = controlName; item.RegisterCallback(_ => SelectControl(control)); foldout.Add(item); } } } private void CreatePreviewArea(VisualElement parent) { var preview = new VisualElement { name = "preview" }; preview.AddToClassList(UssClasses.Preview); parent.Add(preview); _previewTitle = new Label("Select a control"); _previewTitle.AddToClassList(UssClasses.PreviewTitle); preview.Add(_previewTitle); var previewScroll = new ScrollView(ScrollViewMode.Vertical); previewScroll.AddToClassList(UssClasses.PreviewScroll); preview.Add(previewScroll); _previewContent = new VisualElement { name = "preview-content" }; _previewContent.AddToClassList(UssClasses.PreviewContent); previewScroll.Add(_previewContent); } #endregion #region Control Selection private void SelectControl(string controlName) { if (_root == null || _previewContent == null || _previewTitle == null) return; _selectedItem?.RemoveFromClassList(UssClasses.ControlItemSelected); _selectedControl = controlName; _selectedItem = _root.Q($"item-{controlName}"); _selectedItem?.AddToClassList(UssClasses.ControlItemSelected); _previewTitle.text = controlName; _previewContent.Clear(); LoadControlPreview(controlName, _previewContent); } /// /// UXML 파일을 로드하고 필요한 초기화를 수행합니다. /// private void LoadControlPreview(string controlName, VisualElement container) { if (!ControlUxmlPaths.TryGetValue(controlName, out var uxmlPath)) { container.Add(new Label($"UXML not found for {controlName}")); return; } // UXML 로드 (캐싱) if (!_uxmlCache.TryGetValue(uxmlPath, out var uxml)) { uxml = Resources.Load(uxmlPath); if (uxml != null) { _uxmlCache[uxmlPath] = uxml; } } if (uxml == null) { container.Add(new Label($"Failed to load UXML: {uxmlPath}")); return; } // UXML 인스턴스화 var instance = uxml.Instantiate(); container.Add(instance); // 컴포넌트별 초기화 InitializeControl(controlName, instance); // 코드 샘플 추가 AddCodeSample(controlName, container); } /// /// 컴포넌트별 코드 샘플을 추가합니다. /// private void AddCodeSample(string controlName, VisualElement container) { if (!CodeSamples.TryGetValue(controlName, out var samples)) return; var codeSampleContainer = UTKCodeBlock.CreateCodeSampleContainer(samples.CSharp, samples.Uxml); container.Add(codeSampleContainer); } /// /// UXML에서 로드된 UTKCodeBlock에 코드 샘플을 설정합니다. /// private void SetCodeSamples(VisualElement root, string? csharpCode = null, string? uxmlCode = null, string? iconCode = null) { if (csharpCode != null) { var codeCSharp = root.Q("code-csharp"); if (codeCSharp != null) { codeCSharp.Code = csharpCode; } } if (uxmlCode != null) { var codeUxml = root.Q("code-uxml"); if (codeUxml != null) { codeUxml.Code = uxmlCode; } } if (iconCode != null) { var codeIcon = root.Q("code-icon"); if (codeIcon != null) { codeIcon.Code = iconCode; } } } /// /// UXML 로드 후 컴포넌트별 추가 초기화를 수행합니다. /// private void InitializeControl(string controlName, VisualElement root) { switch (controlName) { // Button case "UTKButton": InitializeButtonSample(root); break; case "UTKCheckBox": InitializeCheckBoxSample(root); break; case "UTKToggle": InitializeToggleSample(root); break; case "UTKRadioButton": InitializeRadioButtonSample(root); break; case "UTKToggleButtonGroup": InitializeToggleButtonGroupSample(root); break; case "UTKImageToggleButton": InitializeImageToggleButtonSample(root); break; // Input case "UTKInputField": InitializeInputFieldSample(root); break; case "UTKIntegerField": InitializeIntegerFieldSample(root); break; case "UTKLongField": InitializeLongFieldSample(root); break; case "UTKFloatField": InitializeFloatFieldSample(root); break; case "UTKDoubleField": InitializeDoubleFieldSample(root); break; case "UTKIntStepper": InitializeNumberStepperSample(root); break; case "UTKFloatStepper": InitializeFloatStepperSample(root); break; case "UTKVector2Field": InitializeVector2FieldSample(root); break; case "UTKVector3Field": InitializeVector3FieldSample(root); break; case "UTKVector4Field": InitializeVector4FieldSample(root); break; case "UTKRectField": InitializeRectFieldSample(root); break; case "UTKBoundsField": InitializeBoundsFieldSample(root); break; // Slider case "UTKSlider": InitializeSliderSample(root); break; case "UTKSliderInt": InitializeSliderIntSample(root); break; case "UTKMinMaxSlider": InitializeMinMaxSliderSample(root); break; case "UTKProgressBar": InitializeProgressBarSample(root); break; // Dropdown case "UTKDropdown": InitializeDropdownSample(root); break; case "UTKEnumDropDown": InitializeEnumDropDownSample(root); break; case "UTKMultiSelectDropdown": InitializeMultiSelectDropdownSample(root); break; case "UTKButtonDropdown": InitializeButtonDropdownSample(root); break; // Label case "UTKLabel": InitializeLabelSample(root); break; case "UTKHelpBox": InitializeHelpBoxSample(root); break; // List case "UTKListView": InitializeListViewSample(root); break; case "UTKTreeView": InitializeTreeViewSample(root); break; case "UTKMultiColumnListView": InitializeMultiColumnListViewSample(root); break; case "UTKMultiColumnTreeView": InitializeMultiColumnTreeViewSample(root); break; case "UTKFoldout": InitializeFoldoutSample(root); break; case "UTKScrollView": InitializeScrollViewSample(root); break; case "UTKShortcutList": InitializeShortcutListSample(root); break; case "UTKReordableList": InitializeReordableListSample(root); break; case "UTKReordableTabList": InitializeReordableTabListSample(root); break; // Card case "UTKCard": InitializeCardSample(root); break; case "UTKPanel": InitializePanelSample(root); break; // Tab case "UTKTabView": InitializeTabViewSample(root); break; // Modal case "UTKAlert": InitializeAlertSample(root); break; case "UTKToast": InitializeToastSample(root); break; case "UTKTooltip": InitializeTooltipSample(root); break; case "UTKNotification": InitializeNotificationSample(root); break; case "UTKModal": InitializeModalSample(root); break; case "UTKLoading": InitializeLoadingSample(root); break; // Picker case "UTKColorPicker": InitializeColorPickerSample(root); break; case "UTKDatePicker": InitializeDatePickerSample(root); break; // Icon case "UTKMaterialIcons": InitializeUTKMaterialIconsSample(root); break; case "UTKImageIcons": InitializeImageIconsSample(root); break; case "UTKImage": InitializeUTKImageSample(root); break; // Menu case "UTKTopMenu": InitializeTopMenuSample(root); break; // ToolBar case "UTKToolBar": InitializeToolBarSample(root); break; // Window case "UTKAccordionListWindow": InitializeAccordionListWindowSample(root); break; case "UTKComponentListWindow": InitializeComponentListWindowSample(root); break; case "UTKComponentTabListWindow": InitializeComponentTabListWindowSample(root); break; case "UTKImageListWindow": InitializeImageListWindowSample(root); break; case "UTKTreeListWindow": InitializeTreeListWindowSample(root); break; case "UTKPropertyListWindow": InitializePropertyListWindowSample(root); break; case "UTKSideBar": InitializeSideBarSample(root); break; } } #endregion }