Dropdown 샘플코드 갱신. Tab align 기능 추가

This commit is contained in:
김형인
2026-02-07 00:15:41 +09:00
parent a7fc12f32f
commit a38efd756e
9 changed files with 549 additions and 49 deletions

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<UXML xmlns="UnityEngine.UIElements" xmlns:utk="UVC.UIToolkit">
<Style src="../UTKSampleCommon.uss" />
<VisualElement class="utk-sample-container">
<Label class="utk-sample-desc" text="다중 선택 드롭다운 컴포넌트" />
<!-- Normal -->
<VisualElement class="utk-sample-section">
<Label class="utk-sample-section__title" text="Normal" />
<VisualElement class="utk-sample-row" name="multiselect-normal-row">
<!-- UTKMultiSelectDropdown will be created via C# to set options -->
</VisualElement>
</VisualElement>
<!-- Disabled -->
<VisualElement class="utk-sample-section">
<Label class="utk-sample-section__title" text="Disabled" />
<VisualElement class="utk-sample-row" name="multiselect-disabled-row">
<!-- Disabled UTKMultiSelectDropdown will be created via C# -->
</VisualElement>
</VisualElement>
<!-- Code Sample -->
<VisualElement class="utk-code-sample-container">
<utk:UTKCodeBlock name="code-csharp" title="C#" />
<utk:UTKCodeBlock name="code-uxml" title="UXML" />
</VisualElement>
</VisualElement>
</UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3f8a9c2d7e1b4f6a9d5c8e2b1a4f7c9e
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -6,6 +6,9 @@
*/
.utk-sample-tabview-container {
width: 400px;
height: 200px;
width: 100%;
min-height: 220px;
margin-bottom: var(--space-m);
align-items: flex-start;
justify-content: flex-start;
}

View File

@@ -6,10 +6,35 @@
<VisualElement class="utk-sample-container">
<Label class="utk-sample-desc" text="탭 뷰 컴포넌트" />
<!-- Top Alignment -->
<VisualElement class="utk-sample-section">
<Label class="utk-sample-section__title" text="TabView" />
<VisualElement name="tabview-container" class="utk-sample-tabview-container">
<!-- UTKTabView will be created via C# to add tabs dynamically -->
<Label class="utk-sample-section__title" text="Top Alignment (Default)" />
<VisualElement name="tabview-top-container" class="utk-sample-tabview-container">
<!-- UTKTabView with Top alignment will be created via C# -->
</VisualElement>
</VisualElement>
<!-- Bottom Alignment -->
<VisualElement class="utk-sample-section">
<Label class="utk-sample-section__title" text="Bottom Alignment" />
<VisualElement name="tabview-bottom-container" class="utk-sample-tabview-container">
<!-- UTKTabView with Bottom alignment will be created via C# -->
</VisualElement>
</VisualElement>
<!-- Left Alignment -->
<VisualElement class="utk-sample-section">
<Label class="utk-sample-section__title" text="Left Alignment" />
<VisualElement name="tabview-left-container" class="utk-sample-tabview-container">
<!-- UTKTabView with Left alignment will be created via C# -->
</VisualElement>
</VisualElement>
<!-- Right Alignment -->
<VisualElement class="utk-sample-section">
<Label class="utk-sample-section__title" text="Right Alignment" />
<VisualElement name="tabview-right-container" class="utk-sample-tabview-container">
<!-- UTKTabView with Right alignment will be created via C# -->
</VisualElement>
</VisualElement>

View File

@@ -19,10 +19,7 @@
Tab Header Strip
=================================== */
.utk-tabview > .unity-tab-view__header-container {
flex-direction: row;
border-bottom-width: var(--border-width);
border-bottom-color: var(--color-border);
.utk-tabview .unity-tab-view__header-container {
background-color: transparent;
}
@@ -94,6 +91,105 @@
right: 0;
}
.utk-tabview .unity-tab__header:checked > .unity-tab__header-underline {
.utk-tabview .unity-tab__header:checked .unity-tab__header-underline {
background-color: var(--color-btn-primary) ;
}
.utk-tabview .unity-tab-view__content-viewport {
align-items: stretch;
}
/* ===================================
Tab Alignment Modes
=================================== */
/* Top Alignment (Default) - 탭이 위쪽에 배치 */
.utk-tabview.utk-tabview--align-top {
flex-direction: column;
}
.utk-tabview.utk-tabview--align-top .unity-tab-view__header-container {
flex-direction: row;
border-bottom-width: var(--border-width);
border-bottom-color: var(--color-border);
border-top-width: 0;
border-left-width: 0;
border-right-width: 0;
flex-grow: 1;
}
/* Bottom Alignment - 탭이 아래쪽에 배치 */
.utk-tabview.utk-tabview--align-bottom {
flex-direction: column-reverse;
}
.utk-tabview.utk-tabview--align-bottom .unity-tab-view__header-container {
flex-direction: row;
border-top-width: var(--border-width);
border-top-color: var(--color-border);
border-bottom-width: 0;
border-left-width: 0;
border-right-width: 0;
flex-grow: 1;
}
.utk-tabview.utk-tabview--align-bottom .unity-tab__header-underline {
bottom: auto;
top: 0;
}
/* Left Alignment - 탭이 왼쪽에 세로로 배치 */
.utk-tabview.utk-tabview--align-left {
flex-direction: row;
}
.utk-tabview.utk-tabview--align-left .unity-tab-view__header-container {
flex-direction: column;
border-right-width: var(--border-width);
border-right-color: var(--color-border);
border-bottom-width: 0;
border-top-width: 0;
border-left-width: 0;
}
.utk-tabview.utk-tabview--align-left .unity-tab__header {
margin-right: 0;
margin-bottom: var(--space-s);
}
.utk-tabview.utk-tabview--align-left .unity-tab__header-underline {
left: auto;
right: 0;
bottom: 0;
top: 0;
width: 2px;
height: auto;
}
/* Right Alignment - 탭이 오른쪽에 세로로 배치 */
.utk-tabview.utk-tabview--align-right {
flex-direction: row-reverse;
}
.utk-tabview.utk-tabview--align-right .unity-tab-view__header-container {
flex-direction: column;
border-left-width: var(--border-width);
border-left-color: var(--color-border);
border-bottom-width: 0;
border-top-width: 0;
border-right-width: 0;
}
.utk-tabview.utk-tabview--align-right .unity-tab__header {
margin-right: 0;
margin-bottom: var(--space-s);
}
.utk-tabview.utk-tabview--align-right .unity-tab__header-underline {
right: auto;
left: 0;
bottom: 0;
top: 0;
width: 2px;
height: auto;
}

View File

@@ -449,12 +449,15 @@ var dropdown = new UTKDropdown(""Select Option"");
dropdown.SetOptions(new List<string> { ""Option 1"", ""Option 2"", ""Option 3"", ""Option 4"" });
dropdown.SelectedIndex = 0;
// 선택 이벤트
dropdown.OnSelectionChanged += (index) =>
// 선택 이벤트 (인덱스와 값 모두 전달)
dropdown.OnSelectionChanged += (index, value) =>
{
Debug.Log($""선택된 인덱스: {index}"");
Debug.Log($""선택: [{index}] {value}"");
};
// 생성자로 한 번에 설정
var sortDropdown = new UTKDropdown(""정렬"", new List<string> { ""이름"", ""날짜"", ""크기"" });
// 선택된 값 가져오기
var selectedIndex = dropdown.SelectedIndex;
var selectedValue = dropdown.SelectedValue;
@@ -462,22 +465,42 @@ var selectedValue = dropdown.SelectedValue;
// 옵션 동적 변경
dropdown.SetOptions(new List<string> { ""New 1"", ""New 2"", ""New 3"" });
// 프로그램으로 선택
// 프로그램으로 선택 (인덱스로)
dropdown.SelectedIndex = 2;
// 프로그램으로 선택 (값으로)
dropdown.SetSelectedValue(""Option 2"");
// 이벤트 없이 값 변경 (초기화 시 유용)
sortDropdown.SetSelectedValue(""크기"", notify: false);
// 동적으로 옵션 추가
dropdown.AddOption(""Option 5"");
// Disabled
var disabledDropdown = new UTKDropdown(""Disabled"");
disabledDropdown.SetOptions(new List<string> { ""Option 1"", ""Option 2"" });
disabledDropdown.SelectedIndex = 0;
disabledDropdown.IsEnabled = false;",
uxmlCode: @"<!-- UTKDropdown은 동적 생성 권장 -->
<!-- C# 코드에서 SetOptions로 옵션 설정 -->
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 기본 드롭다운 -->
<utk:UTKDropdown name=""dropdown-1"" text=""Select Option"" />
<!-- 기본 드롭다운 (쉼표로 구분) -->
<utk:UTKDropdown label=""정렬"" choices=""이름,날짜,크기"" />
<!-- Disabled -->
<utk:UTKDropdown name=""dropdown-2"" text=""Disabled"" is-enabled=""false"" />");
<!-- 기본값 지정 (index로) -->
<utk:UTKDropdown label=""언어"" choices=""한국어,English,日本語"" index=""0"" />
<!-- 플레이스홀더 사용 -->
<utk:UTKDropdown label=""국가"" choices=""한국,미국,일본,중국"" placeholder=""국가를 선택하세요"" />
<!-- 비활성화 -->
<utk:UTKDropdown label=""선택"" choices=""옵션1,옵션2,옵션3"" index=""1"" is-enabled=""false"" />
<!-- C# 코드에서 SetOptions로 동적 설정 권장 -->
<utk:UTKDropdown name=""dropdown-1"" label=""Select Option"" />
</ui:UXML>");
}
private enum SampleEnum { Option1, Option2, Option3 }
@@ -494,34 +517,163 @@ disabledDropdown.IsEnabled = false;",
SetCodeSamples(root,
csharpCode: @"// Enum 정의
public enum SampleEnum { Option1, Option2, Option3 }
public enum Difficulty { Easy, Normal, Hard, Expert }
// 기본 사용법
// 기본 사용법 (생성자로 label과 기본값 지정)
var enumField = new UTKEnumDropDown(""Choice"", SampleEnum.Option1);
// 값 변경 이벤트
enumField.OnValueChanged += (newValue) =>
{
Debug.Log($""선택된 값: {newValue}"");
// Enum으로 캐스팅하여 사용
if (newValue is SampleEnum sample)
{
Debug.Log($""SampleEnum: {sample}"");
}
};
// 난이도 선택 예시
var difficultyDropdown = new UTKEnumDropDown(""난이도"", Difficulty.Normal);
difficultyDropdown.OnValueChanged += (value) =>
{
var difficulty = (Difficulty)value;
Debug.Log($""난이도 변경: {difficulty}"");
};
// 현재 선택된 값 가져오기
var currentValue = enumField.Value;
if (currentValue is SampleEnum sample)
{
Debug.Log($""현재 값: {sample}"");
}
// 프로그램으로 값 변경
enumField.Value = SampleEnum.Option2;
// 이벤트 없이 값 변경
enumField.SetValue(SampleEnum.Option3, notify: false);
// Disabled
enumField.IsEnabled = false;",
uxmlCode: @"<!-- UTKEnumDropDown은 동적 생성 권장 -->
<!-- C# 코드에서 enum 타입과 초기값 지정 -->
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- UTKEnumDropDown은 동적 생성 권장 -->
<!-- C# 코드에서 enum 타입과 초기값으로 Init() 호출 필수 -->
<!-- 기본 Enum 드롭다운 -->
<utk:UTKEnumDropDown name=""enum-dropdown-1"" label=""Choice"" />
<!-- Disabled -->
<utk:UTKEnumDropDown name=""enum-dropdown-2"" label=""Choice"" is-enabled=""false"" />");
<utk:UTKEnumDropDown name=""enum-dropdown-2"" label=""Choice"" is-enabled=""false"" />
</ui:UXML>
<!-- C#에서 초기화 예시 -->
<!--
var enumDropdown = root.Q<UTKEnumDropDown>(""enum-dropdown-1"");
enumDropdown.Init(SampleEnum.Option1); // 필수!
-->");
}
private void InitializeMultiSelectDropdownSample(VisualElement root)
{
var normalRow = root.Q<VisualElement>("multiselect-normal-row");
if (normalRow != null)
{
var dropdown = new UTKMultiSelectDropdown("Select Categories");
dropdown.SetOptions(new List<string> { "Category 1", "Category 2", "Category 3", "Category 4", "Category 5" });
dropdown.SetSelectedIndices(new List<int> { 0, 2 });
normalRow.Add(dropdown);
}
var disabledRow = root.Q<VisualElement>("multiselect-disabled-row");
if (disabledRow != null)
{
var dropdown = new UTKMultiSelectDropdown("Disabled");
dropdown.SetOptions(new List<string> { "Option 1", "Option 2", "Option 3" });
dropdown.SetSelectedIndices(new List<int> { 0, 1 });
dropdown.IsEnabled = false;
disabledRow.Add(dropdown);
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var dropdown = new UTKMultiSelectDropdown(""Select Categories"");
dropdown.SetOptions(new List<string> { ""Category 1"", ""Category 2"", ""Category 3"", ""Category 4"", ""Category 5"" });
// 선택 이벤트 (인덱스 목록과 값 목록 모두 전달)
dropdown.OnSelectionChanged += (indices, values) =>
{
Debug.Log($""선택된 개수: {values.Count}"");
Debug.Log($""선택 항목: {string.Join("", "", values)}"");
Debug.Log($""인덱스: [{string.Join("", "", indices)}]"");
};
// 생성자로 한 번에 설정
var categoryDropdown = new UTKMultiSelectDropdown(
""카테고리 선택"",
new List<string> { ""과일"", ""채소"", ""육류"", ""유제품"" }
);
// 기본값 설정 (인덱스로)
categoryDropdown.SetSelectedIndices(new List<int> { 0, 2 });
// 기본값 설정 (값으로)
categoryDropdown.SetSelectedValues(new List<string> { ""과일"", ""육류"" });
// 이벤트 없이 선택 변경 (초기화 시 유용)
categoryDropdown.SetSelectedIndices(new List<int> { 1, 3 }, notify: false);
// 선택된 값 가져오기
var selectedIndices = dropdown.SelectedIndices;
var selectedValues = dropdown.SelectedValues;
// 전체 선택
dropdown.SelectAll();
// 전체 해제
dropdown.ClearSelection();
// 옵션 동적 변경
dropdown.SetOptions(new List<string> { ""New 1"", ""New 2"", ""New 3"" });
// Disabled
var disabledDropdown = new UTKMultiSelectDropdown(""Disabled"");
disabledDropdown.SetOptions(new List<string> { ""Option 1"", ""Option 2"", ""Option 3"" });
disabledDropdown.SetSelectedIndices(new List<int> { 0, 1 });
disabledDropdown.IsEnabled = false;",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 기본 다중 선택 드롭다운 (쉼표로 구분) -->
<utk:UTKMultiSelectDropdown label=""카테고리"" choices=""과일,채소,육류,유제품"" />
<!-- 기본값 지정 (인덱스로) -->
<utk:UTKMultiSelectDropdown label=""태그""
choices=""중요,긴급,검토 필요,완료""
selected-indices=""0,1"" />
<!-- 플레이스홀더 사용 -->
<utk:UTKMultiSelectDropdown label=""필터""
choices=""전체,활성,비활성,대기중""
placeholder=""필터를 선택하세요"" />
<!-- 비활성화 -->
<utk:UTKMultiSelectDropdown label=""선택""
choices=""옵션1,옵션2,옵션3""
selected-indices=""0,2""
is-enabled=""false"" />
<!-- C# 코드에서 SetOptions로 동적 설정 권장 -->
<utk:UTKMultiSelectDropdown name=""multiselect-1"" label=""Select Options"" />
</ui:UXML>");
}
#endregion
#region Slider Initializers
private void InitializeSliderSample(VisualElement root)
@@ -683,6 +835,4 @@ async UniTask LoadDataAsync()
}
#endregion
#endregion
}

View File

@@ -15,30 +15,96 @@ public partial class UTKStyleGuideSample
private void InitializeTabViewSample(VisualElement root)
{
var tabContainer = root.Q<VisualElement>("tabview-container");
if (tabContainer != null)
// Top Alignment (기본)
var tabContainerTop = root.Q<VisualElement>("tabview-top-container");
if (tabContainerTop != null)
{
var tabView = new UTKTabView();
tabView.style.width = 400;
tabView.Align = TabAlign.Top;
tabView.style.width = 500;
tabView.style.height = 200;
tabView.AddUTKTab("Tab 1", new Label("Content for Tab 1"));
tabView.AddUTKTab("Tab 2", new Label("Content for Tab 2"));
tabView.AddUTKTab("Tab 3", new Label("Content for Tab 3"));
tabView.AddUTKTab("일반", new Label("일반 설정 내용입니다.\n탭이 위쪽에 배치됩니다."));
tabView.AddUTKTab("고급", new Label("고급 설정 내용입니다."));
tabView.AddUTKTab("정보", new Label("정보 탭 내용입니다."));
tabContainer.Add(tabView);
tabContainerTop.Add(tabView);
}
// Bottom Alignment
var tabContainerBottom = root.Q<VisualElement>("tabview-bottom-container");
if (tabContainerBottom != null)
{
var tabView = new UTKTabView();
tabView.Align = TabAlign.Bottom;
tabView.style.width = 500;
tabView.style.height = 200;
tabView.AddUTKTab("일반", new Label("일반 설정 내용입니다.\n탭이 아래쪽에 배치됩니다."));
tabView.AddUTKTab("고급", new Label("고급 설정 내용입니다."));
tabView.AddUTKTab("정보", new Label("정보 탭 내용입니다."));
tabContainerBottom.Add(tabView);
}
// Left Alignment
var tabContainerLeft = root.Q<VisualElement>("tabview-left-container");
if (tabContainerLeft != null)
{
var tabView = new UTKTabView();
tabView.Align = TabAlign.Left;
tabView.style.width = 500;
tabView.style.height = 200;
tabView.AddUTKTab("일반", new Label("일반 설정 내용입니다.\n탭이 왼쪽에 세로로 배치됩니다."));
tabView.AddUTKTab("고급", new Label("고급 설정 내용입니다."));
tabView.AddUTKTab("정보", new Label("정보 탭 내용입니다."));
tabContainerLeft.Add(tabView);
}
// Right Alignment
var tabContainerRight = root.Q<VisualElement>("tabview-right-container");
if (tabContainerRight != null)
{
var tabView = new UTKTabView();
tabView.Align = TabAlign.Right;
tabView.style.width = 500;
tabView.style.height = 200;
tabView.AddUTKTab("일반", new Label("일반 설정 내용입니다.\n탭이 오른쪽에 세로로 배치됩니다."));
tabView.AddUTKTab("고급", new Label("고급 설정 내용입니다."));
tabView.AddUTKTab("정보", new Label("정보 탭 내용입니다."));
tabContainerRight.Add(tabView);
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
csharpCode: @"// 기본 사용법 (Top Alignment)
var tabView = new UTKTabView();
tabView.style.width = 400;
tabView.Align = TabAlign.Top; // 기본값
tabView.style.width = 500;
tabView.style.height = 200;
// 탭 추가
tabView.AddUTKTab(""Tab 1"", new Label(""Content for Tab 1""));
tabView.AddUTKTab(""Tab 2"", new Label(""Content for Tab 2""));
tabView.AddUTKTab(""Tab 3"", new Label(""Content for Tab 3""));
tabView.AddUTKTab(""일반"", new Label(""일반 설정 내용""));
tabView.AddUTKTab(""고급"", new Label(""고급 설정 내용""));
tabView.AddUTKTab(""정보"", new Label(""정보 탭 내용""));
// Bottom Alignment - 탭이 아래쪽에 배치
var tabViewBottom = new UTKTabView();
tabViewBottom.Align = TabAlign.Bottom;
tabViewBottom.AddUTKTab(""Tab 1"", new Label(""Content 1""));
// Left Alignment - 탭이 왼쪽에 세로로 배치
var tabViewLeft = new UTKTabView();
tabViewLeft.Align = TabAlign.Left;
tabViewLeft.AddUTKTab(""Tab 1"", new Label(""Content 1""));
// Right Alignment - 탭이 오른쪽에 세로로 배치
var tabViewRight = new UTKTabView();
tabViewRight.Align = TabAlign.Right;
tabViewRight.AddUTKTab(""Tab 1"", new Label(""Content 1""));
// 복잡한 콘텐츠 추가
var contentContainer = new VisualElement();
@@ -46,22 +112,64 @@ contentContainer.Add(new Label(""복잡한 콘텐츠""));
contentContainer.Add(new UTKButton(""버튼""));
tabView.AddUTKTab(""Tab 4"", contentContainer);
// 탭 선택 이벤트
tabView.OnTabChanged += (index) =>
// 탭 변경 이벤트
tabView.OnTabChanged += (index, tab) =>
{
Debug.Log($""선택된 탭 인덱스: {index}"");
};
// 프로그램으로 탭 선택
tabView.SelectTab(1); // 두 번째 탭 선택
tabView.SelectedIndex = 1; // 두 번째 탭 선택
// 현재 선택된 탭 인덱스
var currentTab = tabView.SelectedTabIndex;",
uxmlCode: @"<!-- UTKTabView는 동적 생성 권장 -->
<!-- C# 코드에서 AddUTKTab으로 탭 추가 -->
var currentTab = tabView.SelectedIndex;",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 기본 TabView -->
<utk:UTKTabView name=""tab-view-1"" style=""width: 400px; height: 200px;"" />");
<!-- Top Alignment (기본값) -->
<utk:UTKTabView align=""Top"" style=""width: 500px; height: 200px;"">
<utk:UTKTab label=""일반"">
<ui:Label text=""일반 설정 내용"" />
</utk:UTKTab>
<utk:UTKTab label=""고급"">
<ui:Label text=""고급 설정 내용"" />
</utk:UTKTab>
</utk:UTKTabView>
<!-- Bottom Alignment - 탭이 아래쪽 -->
<utk:UTKTabView align=""Bottom"" style=""width: 500px; height: 200px;"">
<utk:UTKTab label=""Tab 1"">
<ui:Label text=""Content 1"" />
</utk:UTKTab>
<utk:UTKTab label=""Tab 2"">
<ui:Label text=""Content 2"" />
</utk:UTKTab>
</utk:UTKTabView>
<!-- Left Alignment - 탭이 왼쪽 (세로) -->
<utk:UTKTabView align=""Left"" style=""width: 500px; height: 200px;"">
<utk:UTKTab label=""Tab 1"">
<ui:Label text=""Content 1"" />
</utk:UTKTab>
<utk:UTKTab label=""Tab 2"">
<ui:Label text=""Content 2"" />
</utk:UTKTab>
</utk:UTKTabView>
<!-- Right Alignment - 탭이 오른쪽 (세로) -->
<utk:UTKTabView align=""Right"" style=""width: 500px; height: 200px;"">
<utk:UTKTab label=""Tab 1"">
<ui:Label text=""Content 1"" />
</utk:UTKTab>
<utk:UTKTab label=""Tab 2"">
<ui:Label text=""Content 2"" />
</utk:UTKTab>
</utk:UTKTabView>
<!-- 동적 생성도 권장 -->
<utk:UTKTabView name=""tab-view-1"" align=""Top"" />
</ui:UXML>");
}
#endregion

View File

@@ -76,6 +76,7 @@ public partial class UTKStyleGuideSample : MonoBehaviour
// Dropdown
["UTKDropdown"] = "UIToolkit/Sample/Dropdown/UTKDropdownSample",
["UTKEnumDropDown"] = "UIToolkit/Sample/Dropdown/UTKEnumDropDownSample",
["UTKMultiSelectDropdown"] = "UIToolkit/Sample/Dropdown/UTKMultiSelectDropdownSample",
// Label
["UTKLabel"] = "UIToolkit/Sample/Label/UTKLabelSample",
["UTKHelpBox"] = "UIToolkit/Sample/Label/UTKHelpBoxSample",
@@ -112,7 +113,7 @@ public partial class UTKStyleGuideSample : MonoBehaviour
["Button"] = new[] { "UTKButton", "UTKCheckBox", "UTKToggle", "UTKRadioButton", "UTKToggleButtonGroup" },
["Input"] = new[] { "UTKInputField", "UTKIntegerField", "UTKLongField", "UTKFloatField", "UTKDoubleField", "UTKVector2Field", "UTKVector3Field", "UTKVector4Field", "UTKRectField", "UTKBoundsField", "UTKNumberStepper" },
["Slider"] = new[] { "UTKSlider", "UTKSliderInt", "UTKMinMaxSlider", "UTKProgressBar" },
["Dropdown"] = new[] { "UTKDropdown", "UTKEnumDropDown" },
["Dropdown"] = new[] { "UTKDropdown", "UTKEnumDropDown", "UTKMultiSelectDropdown" },
["Label"] = new[] { "UTKLabel", "UTKHelpBox" },
["List"] = new[] { "UTKListView", "UTKTreeView", "UTKMultiColumnListView", "UTKMultiColumnTreeView", "UTKFoldout", "UTKScrollView" },
["Card"] = new[] { "UTKCard", "UTKPanel" },
@@ -485,6 +486,9 @@ public partial class UTKStyleGuideSample : MonoBehaviour
case "UTKEnumDropDown":
InitializeEnumDropDownSample(root);
break;
case "UTKMultiSelectDropdown":
InitializeMultiSelectDropdownSample(root);
break;
// Label
case "UTKLabel":
InitializeLabelSample(root);

View File

@@ -6,6 +6,21 @@ using UnityEngine.UIElements;
namespace UVC.UIToolkit
{
/// <summary>
/// 탭 정렬 방향
/// </summary>
public enum TabAlign
{
/// <summary>탭이 위쪽에 배치</summary>
Top,
/// <summary>탭이 아래쪽에 배치</summary>
Bottom,
/// <summary>탭이 왼쪽에 배치 (세로 정렬)</summary>
Left,
/// <summary>탭이 오른쪽에 배치 (세로 정렬)</summary>
Right
}
/// <summary>
/// 탭 뷰 컴포넌트.
/// Unity TabView를 래핑하여 커스텀 스타일을 적용합니다.
@@ -29,6 +44,7 @@ namespace UVC.UIToolkit
/// <list type="bullet">
/// <item><description><c>SelectedIndex</c> - 현재 선택된 탭 인덱스</description></item>
/// <item><description><c>UTKTabs</c> - 탭 목록 (읽기 전용)</description></item>
/// <item><description><c>Align</c> - 탭 정렬 방향 (Top, Bottom, Left, Right)</description></item>
/// </list>
///
/// <para><b>주요 메서드:</b></para>
@@ -59,21 +75,25 @@ namespace UVC.UIToolkit
/// var tabView = new UTKTabView();
///
/// // 탭 추가
/// var tab1 = tabView.AddTab("일반", UTKMaterialIcons.Settings);
/// var tab1 = tabView.AddUTKTab("일반");
/// tab1.Add(new Label("일반 설정 내용"));
///
/// var tab2 = tabView.AddTab("고급", UTKMaterialIcons.Build);
/// var tab2 = tabView.AddUTKTab("고급");
/// tab2.Add(new Label("고급 설정 내용"));
///
/// // 탭 변경 이벤트
/// tabView.OnTabChanged += (index, tab) => Debug.Log($"탭 {index} 선택됨");
///
/// // 탭 정렬 방향 설정
/// tabView.Align = TabAlign.Left; // 탭을 왼쪽에 세로로 배치
///
/// // 탭 선택
/// tabView.SelectedIndex = 0;
/// </code>
/// <para><b>UXML에서 사용:</b></para>
/// <code>
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
/// <!-- 기본 탭 뷰 (위쪽) -->
/// <utk:UTKTabView>
/// <utk:UTKTab label="일반">
/// <ui:Label text="일반 탭 내용" />
@@ -82,6 +102,16 @@ namespace UVC.UIToolkit
/// <ui:Label text="고급 탭 내용" />
/// </utk:UTKTab>
/// </utk:UTKTabView>
///
/// <!-- 탭을 왼쪽에 배치 -->
/// <utk:UTKTabView align="Left">
/// <utk:UTKTab label="탭 1">
/// <ui:Label text="내용 1" />
/// </utk:UTKTab>
/// <utk:UTKTab label="탭 2">
/// <ui:Label text="내용 2" />
/// </utk:UTKTab>
/// </utk:UTKTabView>
/// </ui:UXML>
/// </code>
/// </example>
@@ -95,6 +125,7 @@ namespace UVC.UIToolkit
#region Fields
private bool _disposed;
private readonly List<UTKTab> _utkTabs = new();
private TabAlign _align = TabAlign.Top;
#endregion
#region Events
@@ -112,6 +143,19 @@ namespace UVC.UIToolkit
/// <summary>UTK 탭 목록</summary>
public IReadOnlyList<UTKTab> UTKTabs => _utkTabs;
/// <summary>탭 정렬 방향</summary>
[UxmlAttribute("align")]
public TabAlign Align
{
get => _align;
set
{
if (_align == value) return;
_align = value;
ApplyAlignment();
}
}
#endregion
#region Constructor
@@ -135,6 +179,7 @@ namespace UVC.UIToolkit
private void SetupStyles()
{
AddToClassList("utk-tabview");
ApplyAlignment();
}
private void SetupEvents()
@@ -174,6 +219,35 @@ namespace UVC.UIToolkit
#endregion
#region Methods
/// <summary>
/// 탭 정렬 방향 적용
/// </summary>
private void ApplyAlignment()
{
// 기존 align 클래스 제거
RemoveFromClassList("utk-tabview--align-top");
RemoveFromClassList("utk-tabview--align-bottom");
RemoveFromClassList("utk-tabview--align-left");
RemoveFromClassList("utk-tabview--align-right");
// 새로운 align 클래스 추가
switch (_align)
{
case TabAlign.Top:
AddToClassList("utk-tabview--align-top");
break;
case TabAlign.Bottom:
AddToClassList("utk-tabview--align-bottom");
break;
case TabAlign.Left:
AddToClassList("utk-tabview--align-left");
break;
case TabAlign.Right:
AddToClassList("utk-tabview--align-right");
break;
}
}
/// <summary>
/// UTK 탭 추가
/// </summary>