#nullable enable using System; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UIElements; using UVC.UIToolkit; /// /// UTKStyleGuideSample의 List 카테고리 Initialize 메서드들 /// public partial class UTKStyleGuideSample { #region Label Initializers private void InitializeLabelSample(VisualElement root) { // Material Icon + Text var materialIconRow = root.Q("material-icon-row"); if (materialIconRow != null) { materialIconRow.Add(new UTKLabel("Settings", UTKMaterialIcons.Settings)); materialIconRow.Add(new UTKLabel("Home", UTKMaterialIcons.Home)); materialIconRow.Add(new UTKLabel("Search", UTKMaterialIcons.Search)); materialIconRow.Add(new UTKLabel("Edit", UTKMaterialIcons.Edit)); } // Icon Right var iconRightRow = root.Q("icon-right-row"); if (iconRightRow != null) { iconRightRow.Add(new UTKLabel("Next", UTKMaterialIcons.ArrowForward, UTKLabel.IconPosition.Right)); iconRightRow.Add(new UTKLabel("Download", UTKMaterialIcons.Download, UTKLabel.IconPosition.Right)); iconRightRow.Add(new UTKLabel("External", UTKMaterialIcons.OpenInNew, UTKLabel.IconPosition.Right)); } // Image Icon + Text var imageIconRow = root.Q("image-icon-row"); if (imageIconRow != null) { imageIconRow.Add(new UTKLabel("Close", UTKImageIcons.BtnClose16, isImageIcon: true)); imageIconRow.Add(new UTKLabel("Settings", UTKImageIcons.IconSetting22, isImageIcon: true)); } // Material Icon Only var materialIconOnlyRow = root.Q("material-icon-only-row"); if (materialIconOnlyRow != null) { materialIconOnlyRow.Add(new UTKLabel(UTKMaterialIcons.Home, 24)); materialIconOnlyRow.Add(new UTKLabel(UTKMaterialIcons.Settings, 24)); materialIconOnlyRow.Add(new UTKLabel(UTKMaterialIcons.Search, 24)); materialIconOnlyRow.Add(new UTKLabel(UTKMaterialIcons.Edit, 24)); materialIconOnlyRow.Add(new UTKLabel(UTKMaterialIcons.Delete, 24)); } SetCodeSamples(root, csharpCode: @"// 기본 라벨 var label = new UTKLabel(); label.Text = ""안녕하세요""; label.Size = UTKLabel.LabelSize.Body1; label.Variant = UTKLabel.LabelVariant.Primary; // 제목 스타일 var title = new UTKLabel(); title.Text = ""제목""; title.Size = UTKLabel.LabelSize.Heading1; title.IsBold = true; // Material Icon과 텍스트 함께 사용 var iconLabel = new UTKLabel(""설정"", UTKMaterialIcons.Settings); // Material Icon만 사용 var iconOnly = new UTKLabel(UTKMaterialIcons.Home);", uxmlCode: @" "); } private void InitializeHelpBoxSample(VisualElement root) { SetCodeSamples(root, csharpCode: @"// 기본 도움말 박스 var helpBox = new UTKHelpBox(); helpBox.Text = ""이것은 정보 메시지입니다.""; // 생성자로 생성 var infoBox = new UTKHelpBox(""저장이 완료되었습니다."", UTKHelpBox.MessageType.Info); // 메시지 타입별 var successBox = new UTKHelpBox(""작업 성공!"", UTKHelpBox.MessageType.Success); var warningBox = new UTKHelpBox(""주의가 필요합니다."", UTKHelpBox.MessageType.Warning); var errorBox = new UTKHelpBox(""오류가 발생했습니다."", UTKHelpBox.MessageType.Error); // 메시지 변경 helpBox.Text = ""새로운 메시지""; helpBox.messageType = UTKHelpBox.MessageType.Warning;", uxmlCode: @" "); } #endregion #region List Initializers private void InitializeListViewSample(VisualElement root) { var listView = root.Q("listview-sample"); if (listView != null) { var items = new List(); for (int i = 1; i <= 20; i++) items.Add($"Item {i}"); listView.makeItem = () => new Label(); listView.bindItem = (element, index) => ((Label)element).text = items[index]; listView.itemsSource = items; listView.fixedItemHeight = 24; } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var listView = new UTKListView(); // 데이터 소스 설정 var items = new List(); for (int i = 1; i <= 20; i++) items.Add($""Item {i}""); // makeItem: 각 아이템을 표시할 UI 요소 생성 listView.makeItem = () => new Label(); // bindItem: 데이터를 UI 요소에 바인딩 listView.bindItem = (element, index) => ((Label)element).text = items[index]; // 데이터 소스 설정 listView.itemsSource = items; // 고정 높이 설정 (가상화를 위해 권장) listView.fixedItemHeight = 24; // 선택 이벤트 listView.selectionChanged += (items) => { foreach (var item in items) Debug.Log($""Selected: {item}""); };", uxmlCode: @" "); } private void InitializeTreeViewSample(VisualElement root) { var treeView = root.Q("treeview-sample"); if (treeView != null) { var treeItems = new List> { new(1, "Parent 1", new List> { new(2, "Child 1-1"), new(3, "Child 1-2"), }), new(4, "Parent 2", new List> { new(5, "Child 2-1"), new(6, "Child 2-2", new List> { new(7, "Grandchild 2-2-1"), new(8, "Grandchild 2-2-2"), }), }), new(9, "Parent 3"), }; treeView.SetRootItems(treeItems); treeView.Rebuild(); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var treeView = new UTKTreeView(); // 계층적 데이터 생성 var treeItems = new List> { new(1, ""Parent 1"", new List> { new(2, ""Child 1-1""), new(3, ""Child 1-2""), }), new(4, ""Parent 2"", new List> { new(5, ""Child 2-1""), new(6, ""Child 2-2"", new List> { new(7, ""Grandchild 2-2-1""), new(8, ""Grandchild 2-2-2""), }), }), new(9, ""Parent 3""), }; // 트리 데이터 설정 treeView.SetRootItems(treeItems); treeView.Rebuild(); // 선택 이벤트 treeView.selectionChanged += (items) => { foreach (var item in items) Debug.Log($""Selected: {item}""); };", uxmlCode: @" "); } 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 InitializeMultiColumnListViewSample(VisualElement root) { var listView = root.Q("multicolumn-listview-sample"); if (listView != null) { 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 { 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 }, }; 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}%"; } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var listView = new UTKMultiColumnListView(); // 컴럼 추가 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 { new() { Id = 1, Name = ""Task Alpha"", Status = ""Active"", Progress = 75 }, new() { Id = 2, Name = ""Task Beta"", Status = ""Pending"", Progress = 30 }, }; listView.itemsSource = items; listView.fixedItemHeight = 24; // 각 컴럼에 makeCell과 bindCell 설정 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.OnItemSelected += (index) => Debug.Log($""선택된 행: {index}""); listView.OnItemDoubleClicked += (index) => Debug.Log($""더블클릭: {index}"");", uxmlCode: @" "); } 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 InitializeMultiColumnTreeViewSample(VisualElement root) { var treeView = root.Q("multicolumn-treeview-sample"); if (treeView != null) { 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> { new(1, new SampleTreeItem { Id = 1, Name = "Documents", Type = "Folder", Size = "2.5 GB" }, new List> { new(11, new SampleTreeItem { Id = 11, Name = "Reports", Type = "Folder", Size = "500 MB" }, new List> { 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> { 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(i); ((Label)e).text = item.Name; }; treeView.columns["type"].makeCell = () => new Label(); treeView.columns["type"].bindCell = (e, i) => { var item = treeView.GetItemDataForIndex(i); ((Label)e).text = item.Type; }; treeView.columns["size"].makeCell = () => new Label(); treeView.columns["size"].bindCell = (e, i) => { var item = treeView.GetItemDataForIndex(i); ((Label)e).text = item.Size; }; treeView.ExpandAll(); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var treeView = new UTKMultiColumnTreeView(); // 컴럼 추가 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> { new(1, new SampleTreeItem { Name = ""Documents"", Type = ""Folder"", Size = ""2.5 GB"" }, new List> { new(11, new SampleTreeItem { Name = ""Reports"", Type = ""Folder"", Size = ""500 MB"" }, new List> { new(111, new SampleTreeItem { Name = ""Q1_Report.pdf"", Type = ""PDF"", Size = ""2.3 MB"" }), }), }), }; treeView.SetRootItems(rootItems); treeView.fixedItemHeight = 22; // 각 컴럼에 makeCell과 bindCell 설정 treeView.columns[""name""].makeCell = () => new Label(); treeView.columns[""name""].bindCell = (e, i) => { var item = treeView.GetItemDataForIndex(i); ((Label)e).text = item.Name; }; // 모든 노드 펼치기 treeView.ExpandAll(); // 선택 이벤트 treeView.OnItemSelected += (index) => Debug.Log($""선택된 항목: {index}"");", uxmlCode: @" "); } private void InitializeShortcutListSample(VisualElement root) { var shortcutList = root.Q("shortcut-list-sample"); if (shortcutList != null) { shortcutList.SetData(new System.Collections.Generic.List { new() { Id = "file.new_project", CommandName = "File > New Project", UseCtrl = true, UseShift = false, UseAlt = false, Key = "N" }, new() { Id = "file.open_project", CommandName = "File > Open Project", UseCtrl = true, UseShift = true, UseAlt = false, Key = "O" }, new() { Id = "file.save_project", CommandName = "File > Save Project", UseCtrl = true, UseShift = false, UseAlt = true, Key = "S" }, new() { Id = "file.save_as", CommandName = "File > Save As...", UseCtrl = true, UseShift = true, UseAlt = true, Key = "S" }, new() { Id = "file.export_layout", CommandName = "File > Export > Layout", UseCtrl = true, UseShift = true, UseAlt = false, Key = "L" }, new() { Id = "file.export_gltf", CommandName = "File > Export > glTF", UseCtrl = true, UseShift = true, UseAlt = false, Key = "G" }, new() { Id = "edit.undo", CommandName = "Edit > Undo", UseCtrl = true, UseShift = true, UseAlt = false, Key = "Z" }, new() { Id = "edit.redo", CommandName = "Edit > Redo", UseCtrl = true, UseShift = true, UseAlt = false, Key = "Y" }, new() { Id = "edit.duplicate", CommandName = "Edit > Duplicate", UseCtrl = true, UseShift = true, UseAlt = false, Key = "D" }, new() { Id = "edit.delete", CommandName = "Edit > Delete", UseCtrl = false, UseShift = true, UseAlt = false, Key = "Delete" }, new() { Id = "create.plane", CommandName = "Create > Plane", UseCtrl = true, UseShift = true, UseAlt = false, Key = "V" }, new() { Id = "tool.select", CommandName = "Select Tool", UseCtrl = false, UseShift = false, UseAlt = false, Key = "1" }, }); shortcutList.OnDataChanged += item => Debug.Log($"[StyleGuide] 단축키 변경: {item.CommandName} → {(item.UseCtrl ? "Ctrl+" : "")}{(item.UseShift ? "Shift+" : "")}{(item.UseAlt ? "Alt+" : "")}{item.Key}"); } SetCodeSamples(root, csharpCode: @"// 데이터 생성 var data = new List { new() { Id = ""file.new"", CommandName = ""File > New Project"", UseCtrl = true, UseShift = false, UseAlt = false, Key = ""N"" }, new() { Id = ""edit.undo"", CommandName = ""Edit > Undo"", UseCtrl = true, UseShift = true, UseAlt = false, Key = ""Z"" }, new() { Id = ""edit.delete"", CommandName = ""Edit > Delete"", UseCtrl = false, UseShift = true, UseAlt = false, Key = ""Delete"" }, }; // 리스트 생성 & 데이터 설정 var list = new UTKShortcutList(); list.SetData(data); // 변경 이벤트 (Ctrl/Shift/Alt 체크 또는 Key 캡처 시 발생) list.OnDataChanged += item => { Debug.Log($""{item.CommandName}: Ctrl={item.UseCtrl} Key={item.Key}""); }; // Key 캡처 방법: // 1. Key 필드 클릭 → ""···"" 표시 // 2. 원하는 키 입력 → 자동 저장 // 3. Escape → 취소 (이전 값 복원) // 현재 데이터 가져오기 var current = list.GetData(); // 업데이트된 데이터 다시 적용 current[0].Key = ""F1""; list.SetData(current);", uxmlCode: @" "); } private void InitializeReordableListSample(VisualElement root) { var reordableList = root.Q("reordable-list-sample"); if (reordableList != null) { var listDict = new List> { new() { ["order"] = "0", ["active"] = "True", ["text"] = "온도" }, new() { ["order"] = "1", ["active"] = "False", ["text"] = "습도" }, new() { ["order"] = "2", ["active"] = "True", ["text"] = "압력" }, new() { ["order"] = "3", ["active"] = "True", ["text"] = "풍속" }, new() { ["order"] = "4", ["active"] = "False", ["text"] = "조도" }, }; reordableList.SetData(listDict); reordableList.OnOrderChanged += () => Debug.Log("[StyleGuide] ReordableList 순서 변경됨"); reordableList.OnDataChanged += () => Debug.Log("[StyleGuide] ReordableList 데이터 변경됨"); } SetCodeSamples(root, csharpCode: @"// 리스트 생성 var list = new UTKReordableList(); // ReordableListItemData로 직접 설정 var items = new List { new() { Order = 0, IsActive = true, DisplayText = ""온도"" }, new() { Order = 1, IsActive = false, DisplayText = ""습도"" }, new() { Order = 2, IsActive = true, DisplayText = ""압력"" }, }; list.SetData(items); // Dictionary 형식으로도 설정 가능 var listDict = new List> { new() { [""order""] = ""0"", [""active""] = ""True"", [""text""] = ""온도"" }, new() { [""order""] = ""1"", [""active""] = ""False"", [""text""] = ""습도"" }, }; list.SetData(listDict); // 데이터 가져오기 var data = list.GetData(); // Dictionary 형식으로 변환 var dictResult = list.ToDictionary(); // 이벤트 구독 list.OnOrderChanged += () => Debug.Log(""순서 변경됨""); list.OnDataChanged += () => Debug.Log(""데이터 변경됨""); // 정리 list.Dispose();", uxmlCode: @" "); } private void InitializeReordableTabListSample(VisualElement root) { var tabList = root.Q("reordable-tab-list-sample"); if (tabList != null) { var data = new Dictionary>> { ["센서"] = new() { new() { ["order"] = "0", ["active"] = "True", ["text"] = "온도 센서" }, new() { ["order"] = "1", ["active"] = "True", ["text"] = "습도 센서" }, new() { ["order"] = "2", ["active"] = "False", ["text"] = "압력 센서" }, }, ["장비"] = new() { new() { ["order"] = "0", ["active"] = "True", ["text"] = "컨베이어" }, new() { ["order"] = "1", ["active"] = "False", ["text"] = "로봇암" }, new() { ["order"] = "2", ["active"] = "True", ["text"] = "CNC" }, new() { ["order"] = "3", ["active"] = "True", ["text"] = "AGV" }, }, ["알림"] = new() { new() { ["order"] = "0", ["active"] = "True", ["text"] = "경고" }, new() { ["order"] = "1", ["active"] = "True", ["text"] = "에러" }, } }; tabList.SetData(data); tabList.OnOrderChanged += (tabName, tabIndex) => Debug.Log($"[StyleGuide] [{tabName}] (탭 {tabIndex}) 순서 변경됨"); tabList.OnDataChanged += (tabName, tabIndex) => Debug.Log($"[StyleGuide] [{tabName}] (탭 {tabIndex}) 데이터 변경됨"); } SetCodeSamples(root, csharpCode: @"// 탭별 데이터 설정 var tabList = new UTKReordableTabList(); var data = new Dictionary> { [""센서""] = new() { new() { Order = 0, IsActive = true, DisplayText = ""온도 센서"" }, new() { Order = 1, IsActive = true, DisplayText = ""습도 센서"" }, new() { Order = 2, IsActive = false, DisplayText = ""압력 센서"" }, }, [""장비""] = new() { new() { Order = 0, IsActive = true, DisplayText = ""컨베이어"" }, new() { Order = 1, IsActive = false, DisplayText = ""로봇암"" }, } }; tabList.SetData(data); // Dictionary 형식도 지원 var dictData = new Dictionary>> { [""탭1""] = new() { new() { [""order""] = ""0"", [""active""] = ""True"", [""text""] = ""항목1"" }, } }; tabList.SetData(dictData); // 전체 데이터 가져오기 var allData = tabList.GetData(); // 특정 탭 데이터 가져오기 (이름 또는 인덱스) var sensorData = tabList.GetData(""센서""); var firstTabData = tabList.GetData(0); // Dictionary 형식으로 변환 var dictResult = tabList.ToDictionary(); // 이벤트 구독 (탭 이름, 탭 인덱스 전달) tabList.OnOrderChanged += (tabName, tabIndex) => Debug.Log($""[{tabName}] (탭 {tabIndex}) 순서 변경됨""); tabList.OnDataChanged += (tabName, tabIndex) => Debug.Log($""[{tabName}] (탭 {tabIndex}) 데이터 변경됨""); // SetData 재호출 시 기존 구성 제거 후 재생성 tabList.SetData(newData); // 정리 tabList.Dispose();", uxmlCode: @" "); } private void InitializeScrollViewSample(VisualElement root) { // Horizontal scroll var horizontalContainer = root.Q("horizontal-scroll-container"); if (horizontalContainer != null) { 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); horizontalContainer.Add(horizontalScroll); } // Both scroll var bothContainer = root.Q("both-scroll-container"); if (bothContainer != null) { 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); } bothContainer.Add(bothScroll); } SetCodeSamples(root, csharpCode: @"// 기본 스크롤 뷰 (세로) var scrollView = new UTKScrollView(); scrollView.Add(new Label(""내용 1"")); scrollView.Add(new Label(""내용 2"")); scrollView.Add(new Label(""내용 3"")); // 스크롤 모드 설정 var verticalScroll = new UTKScrollView(); verticalScroll.mode = ScrollViewMode.Vertical; // 세로 스크롤 var horizontalScroll = new UTKScrollView(); horizontalScroll.mode = ScrollViewMode.Horizontal; // 가로 스크롤 horizontalScroll.style.height = 150; horizontalScroll.style.width = 200; var bothScroll = new UTKScrollView(); bothScroll.mode = ScrollViewMode.VerticalAndHorizontal; // 양방향 스크롤 // 스크롤 위치 제어 scrollView.scrollOffset = new Vector2(0, 100); // 100px 아래로 스크롤 // 스크롤바 표시 설정 scrollView.verticalScrollerVisibility = ScrollerVisibility.Auto; scrollView.horizontalScrollerVisibility = ScrollerVisibility.Hidden;", uxmlCode: @" "); } private void InitializeFoldoutSample(VisualElement root) { SetCodeSamples(root, csharpCode: @"// 기본 폴드아웃 var foldout = new UTKFoldout(); foldout.Text = ""고급 설정""; foldout.IsExpanded = false; // 콘텐츠 추가 foldout.Add(new Label(""옵션 1"")); foldout.Add(new Label(""옵션 2"")); foldout.Add(new Label(""옵션 3"")); // 생성자로 생성 var settingsFoldout = new UTKFoldout(""설정"", true); // 기본 펼쳐짐 // 펼침/접힘 이벤트 foldout.OnValueChanged += (isExpanded) => Debug.Log($""펼침: {isExpanded}""); // 프로그램으로 제어 foldout.IsExpanded = true; foldout.Toggle();", uxmlCode: @" "); } #endregion }