#nullable enable using System; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UIElements; using UVC.UIToolkit; /// /// UTKStyleGuideSample의 Modal, Tab, Picker 카테고리 Initialize 메서드들 /// public partial class UTKStyleGuideSample { #region Tab Initializer private void InitializeTabViewSample(VisualElement root) { // Top Alignment (기본) var tabContainerTop = root.Q("tabview-top-container"); if (tabContainerTop != null) { var tabView = new UTKTabView(); tabView.Align = TabAlign.Top; tabView.style.width = 500; tabView.style.height = 200; tabView.AddUTKTab("일반", new Label("일반 설정 내용입니다.\n탭이 위쪽에 배치됩니다.")); tabView.AddUTKTab("고급", new Label("고급 설정 내용입니다.")); tabView.AddUTKTab("정보", new Label("정보 탭 내용입니다.")); tabContainerTop.Add(tabView); } // Bottom Alignment var tabContainerBottom = root.Q("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("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("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: @"// 기본 사용법 (Top Alignment) var tabView = new UTKTabView(); tabView.Align = TabAlign.Top; // 기본값 tabView.style.width = 500; tabView.style.height = 200; // 탭 추가 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(); contentContainer.Add(new Label(""복잡한 콘텐츠"")); contentContainer.Add(new UTKButton(""버튼"")); tabView.AddUTKTab(""Tab 4"", contentContainer); // 탭 변경 이벤트 tabView.OnTabChanged += (index, tab) => { Debug.Log($""선택된 탭 인덱스: {index}""); }; // 프로그램으로 탭 선택 tabView.SelectedIndex = 1; // 두 번째 탭 선택 // 현재 선택된 탭 인덱스 var currentTab = tabView.SelectedIndex;", uxmlCode: @" "); } #endregion #region Modal Initializers private void InitializeAlertSample(VisualElement root) { if (_root == null) return; UTKAlert.SetRoot(_root); var btnInfo = root.Q("btn-info"); btnInfo?.RegisterCallback(_ => ShowInfoAlertAsync().Forget()); var btnSuccess = root.Q("btn-success"); btnSuccess?.RegisterCallback(_ => ShowSuccessAlertAsync().Forget()); var btnWarning = root.Q("btn-warning"); btnWarning?.RegisterCallback(_ => ShowWarningAlertAsync().Forget()); var btnError = root.Q("btn-error"); btnError?.RegisterCallback(_ => ShowErrorAlertAsync().Forget()); var btnConfirm = root.Q("btn-confirm"); btnConfirm?.RegisterCallback(_ => ShowConfirmAlertAsync().Forget()); var btnConfirmCustom = root.Q("btn-confirm-custom"); btnConfirmCustom?.RegisterCallback(_ => ShowConfirmCustomLabelsAsync().Forget()); var btnCallback = root.Q("btn-callback"); btnCallback?.RegisterCallback(_ => { UTKAlert.ShowInfo("Callback Style", "This uses callback instead of async.", onClose: () => Debug.Log("Alert closed via callback")); }); var btnConfirmCallback = root.Q("btn-confirm-callback"); btnConfirmCallback?.RegisterCallback(_ => { UTKAlert.ShowConfirm("Confirm", "Do you want to proceed?", onConfirm: () => Debug.Log("Confirmed via callback!"), onCancel: () => Debug.Log("Cancelled via callback!")); }); SetCodeSamples(root, csharpCode: @"// Root 설정 (한 번만) UTKAlert.SetRoot(rootVisualElement); // ======================================== // 1. Async/Await 방식 (권장) // ======================================== // Info Alert await UTKAlert.ShowInfoAsync(""정보"", ""이것은 정보 메시지입니다.""); // Success Alert await UTKAlert.ShowSuccessAsync(""성공"", ""작업이 성공적으로 완료되었습니다!""); // Warning Alert await UTKAlert.ShowWarningAsync(""경고"", ""주의가 필요합니다.""); // Error Alert await UTKAlert.ShowErrorAsync(""오류"", ""오류가 발생했습니다!""); // Confirm Dialog bool result = await UTKAlert.ShowConfirmAsync(""확인"", ""정말 진행하시겠습니까?""); if (result) { Debug.Log(""사용자가 확인을 눌렀습니다.""); } else { Debug.Log(""사용자가 취소를 눌렀습니다.""); } // Confirm with Custom Labels bool deleteResult = await UTKAlert.ShowConfirmAsync( ""항목 삭제"", ""이 항목을 정말 삭제하시겠습니까?"", confirmLabel: ""삭제"", cancelLabel: ""유지"" ); // closeOnBlockerClick 옵션 (배경 클릭 시 닫기) await UTKAlert.ShowInfoAsync(""정보"", ""배경을 클릭해도 닫힙니다."", closeOnBlockerClick: true); // ======================================== // 2. Callback 방식 // ======================================== // Info with Callback UTKAlert.ShowInfo(""정보"", ""콜백 방식입니다."", onClose: () => Debug.Log(""Alert가 닫혔습니다."")); // Confirm with Callback UTKAlert.ShowConfirm(""확인"", ""진행하시겠습니까?"", onConfirm: () => Debug.Log(""확인 클릭!""), onCancel: () => Debug.Log(""취소 클릭!""));"); } private async UniTaskVoid ShowInfoAlertAsync() { await UTKAlert.ShowInfoAsync("Information", "This is an info message."); Debug.Log("Info alert closed"); } private async UniTaskVoid ShowSuccessAlertAsync() { await UTKAlert.ShowSuccessAsync("Success", "Operation completed successfully!", closeOnBlockerClick: true); Debug.Log("Success alert closed"); } private async UniTaskVoid ShowWarningAlertAsync() { await UTKAlert.ShowWarningAsync("Warning", "This is a warning message."); Debug.Log("Warning alert closed"); } private async UniTaskVoid ShowErrorAlertAsync() { await UTKAlert.ShowErrorAsync("Error", "An error has occurred!"); Debug.Log("Error alert closed"); } private async UniTaskVoid ShowConfirmAlertAsync() { bool result = await UTKAlert.ShowConfirmAsync("Confirm", "Are you sure?"); Debug.Log(result ? "Confirmed!" : "Cancelled!"); } private async UniTaskVoid ShowConfirmCustomLabelsAsync() { 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 InitializeToastSample(VisualElement root) { var btnInfo = root.Q("btn-toast-info"); btnInfo?.RegisterCallback(_ => UTKToast.Show("This is an info toast!")); var btnSuccess = root.Q("btn-toast-success"); btnSuccess?.RegisterCallback(_ => UTKToast.ShowSuccess("Operation successful!")); var btnWarning = root.Q("btn-toast-warning"); btnWarning?.RegisterCallback(_ => UTKToast.ShowWarning("Warning: Check your input!")); var btnError = root.Q("btn-toast-error"); btnError?.RegisterCallback(_ => UTKToast.ShowError("An error occurred!")); SetCodeSamples(root, csharpCode: @"// Root 설정 (한 번만) UTKToast.SetRoot(rootVisualElement); // Info Toast (기본) UTKToast.Show(""이것은 정보 토스트입니다!""); // Success Toast UTKToast.ShowSuccess(""작업이 성공적으로 완료되었습니다!""); // Warning Toast UTKToast.ShowWarning(""경고: 입력값을 확인하세요!""); // Error Toast UTKToast.ShowError(""오류가 발생했습니다!""); // 지속 시간 설정 (밀리초) UTKToast.Show(""5초 동안 표시"", 5000); // 사용 예시 public async UniTask SaveDataAsync() { try { await SaveToServerAsync(); UTKToast.ShowSuccess(""데이터가 저장되었습니다.""); } catch (Exception ex) { UTKToast.ShowError($""저장 실패: {ex.Message}""); } }"); } private void InitializeTooltipSample(VisualElement root) { var btnShort = root.Q("btn-short-tooltip"); if (btnShort != null) { UTKTooltipManager.Instance.AttachTooltip(btnShort, "This is a short tooltip."); } var btnLong = root.Q("btn-long-tooltip"); if (btnLong != null) { UTKTooltipManager.Instance.AttachTooltip(btnLong, "This is a longer tooltip message that demonstrates how the tooltip handles multiple lines of text content."); } SetCodeSamples(root, csharpCode: @"// 1. 버튼에 툴팁 연결 var saveButton = new UTKButton("""", UTKMaterialIcons.Save); UTKTooltipManager.Instance.AttachTooltip(saveButton, ""저장 (Ctrl+S)""); // 2. 다국어 키로 툴팁 연결 UTKTooltipManager.Instance.AttachTooltip(settingsButton, ""tooltip_settings""); // 4. 아이콘 버튼에 툴팁 var deleteBtn = new UTKButton("""", UTKMaterialIcons.Delete) { IconOnly = true }; UTKTooltipManager.Instance.AttachTooltip(deleteBtn, ""삭제""); // 5. 툴팁 업데이트 UTKTooltipManager.Instance.UpdateTooltip(button, ""새로운 설명""); // 6. 툴팁 제거 UTKTooltipManager.Instance.DetachTooltip(button); // 7. 즉시 표시 (특정 위치에) UTKTooltipManager.Instance.Show(""임시 정보"", new Vector2(100, 200)); // 8. 숨기기 UTKTooltipManager.Instance.Hide(); // 9. 여러 요소에 툴팁 연결 var buttons = new[] { btn1, btn2, btn3 }; var tooltips = new[] { ""버튼 1"", ""버튼 2"", ""버튼 3"" }; for (int i = 0; i < buttons.Length; i++) { UTKTooltipManager.Instance.AttachTooltip(buttons[i], tooltips[i]); }"); } #endregion #region Modal Initializers (UTKModal) private void InitializeModalSample(VisualElement root) { if (_root == null) return; UTKModal.SetRoot(_root); // Modal Sizes var btnSmall = root.Q("btn-modal-small"); btnSmall?.RegisterCallback(_ => ShowModalWithSize(UTKModal.ModalSize.Small)); var btnMedium = root.Q("btn-modal-medium"); btnMedium?.RegisterCallback(_ => ShowModalWithSize(UTKModal.ModalSize.Medium)); var btnLarge = root.Q("btn-modal-large"); btnLarge?.RegisterCallback(_ => ShowModalWithSize(UTKModal.ModalSize.Large)); var btnFullScreen = root.Q("btn-modal-fullscreen"); btnFullScreen?.RegisterCallback(_ => ShowModalWithSize(UTKModal.ModalSize.FullScreen)); // Options var btnFooter = root.Q("btn-modal-footer"); btnFooter?.RegisterCallback(_ => { var modal = UTKModal.Show("푸터 버튼 모달", UTKModal.ModalSize.Medium); modal.Add(new Label("확인 또는 취소를 선택하세요.")); var confirmBtn = new UTKButton("확인") { Variant = UTKButton.ButtonVariant.Primary }; confirmBtn.RegisterCallback(_ => { Debug.Log("Modal confirmed"); modal.Close(); }); var cancelBtn = new UTKButton("취소") { Variant = UTKButton.ButtonVariant.Normal }; cancelBtn.RegisterCallback(_ => { Debug.Log("Modal cancelled"); modal.Close(); }); modal.AddToFooter(cancelBtn); modal.AddToFooter(confirmBtn); }); var btnNoClose = root.Q("btn-modal-no-close"); btnNoClose?.RegisterCallback(_ => { var modal = UTKModal.Show("닫기 버튼 없음", UTKModal.ModalSize.Small); modal.ShowCloseButton = false; modal.Add(new Label("닫기 버튼이 없습니다.\n배경을 클릭하면 닫힙니다.")); }); var btnNoBackdrop = root.Q("btn-modal-no-backdrop"); btnNoBackdrop?.RegisterCallback(_ => { var modal = UTKModal.Show("배경 클릭 비활성화", UTKModal.ModalSize.Small); modal.CloseOnBackdropClick = false; modal.Add(new Label("배경을 클릭해도 닫히지 않습니다.\nX 버튼으로만 닫을 수 있습니다.")); }); // Custom Content - Form Modal var btnForm = root.Q("btn-modal-form"); btnForm?.RegisterCallback(_ => { var modal = UTKModal.Show("사용자 정보 입력", UTKModal.ModalSize.Medium); var nameField = new UTKInputField("이름"); var emailField = new UTKInputField("이메일"); modal.Add(nameField); modal.Add(emailField); var submitBtn = new UTKButton("제출") { Variant = UTKButton.ButtonVariant.Primary }; submitBtn.RegisterCallback(_ => { Debug.Log($"Name: {nameField.value}, Email: {emailField.value}"); modal.Close(); }); var cancelBtn = new UTKButton("취소") { Variant = UTKButton.ButtonVariant.Normal }; cancelBtn.RegisterCallback(_ => modal.Close()); modal.AddToFooter(cancelBtn); modal.AddToFooter(submitBtn); }); SetCodeSamples(root, csharpCode: @"// Root 설정 (한 번만) UTKModal.SetRoot(rootVisualElement); // ======================================== // 1. 기본 모달 표시 // ======================================== var modal = UTKModal.Show(""제목"", UTKModal.ModalSize.Medium); modal.Add(new Label(""모달 내용"")); // 닫힘 이벤트 modal.OnClosed += () => Debug.Log(""모달 닫힘""); // ======================================== // 2. 모달 크기 // ======================================== // Small UTKModal.Show(""Small"", UTKModal.ModalSize.Small); // Medium (기본) UTKModal.Show(""Medium"", UTKModal.ModalSize.Medium); // Large UTKModal.Show(""Large"", UTKModal.ModalSize.Large); // FullScreen UTKModal.Show(""FullScreen"", UTKModal.ModalSize.FullScreen); // ======================================== // 3. 옵션 설정 // ======================================== var modal = UTKModal.Show(""설정""); // 닫기 버튼 숨기기 modal.ShowCloseButton = false; // 배경 클릭 시 닫기 비활성화 modal.CloseOnBackdropClick = false; // 푸터 숨기기 modal.SetFooterVisible(false); // ======================================== // 4. 푸터 버튼 추가 // ======================================== var modal = UTKModal.Show(""확인 모달""); modal.Add(new Label(""정말 삭제하시겠습니까?"")); var confirmBtn = new UTKButton(""삭제"") { Variant = UTKButton.ButtonVariant.Danger }; confirmBtn.RegisterCallback(_ => { Debug.Log(""삭제 실행""); modal.Close(); }); var cancelBtn = new UTKButton(""취소"") { Variant = UTKButton.ButtonVariant.Normal }; cancelBtn.RegisterCallback(_ => modal.Close()); modal.AddToFooter(cancelBtn); modal.AddToFooter(confirmBtn); // ======================================== // 5. 폼 모달 // ======================================== var modal = UTKModal.Show(""사용자 정보""); var nameField = new UTKInputField(""이름""); var emailField = new UTKInputField(""이메일""); modal.Add(nameField); modal.Add(emailField); var submitBtn = new UTKButton(""제출"") { Variant = UTKButton.ButtonVariant.Primary }; submitBtn.RegisterCallback(_ => { Debug.Log($""Name: {nameField.value}, Email: {emailField.value}""); modal.Close(); }); modal.AddToFooter(submitBtn); // ======================================== // 6. 프로그래밍 방식 닫기 // ======================================== var modal = UTKModal.Show(""타이머 모달""); modal.Add(new Label(""3초 후 자동으로 닫힙니다."")); modal.ShowCloseButton = false; modal.CloseOnBackdropClick = false; // 3초 후 닫기 modal.schedule.Execute(() => modal.Close()).StartingIn(3000);", uxmlCode: @" "); } private void ShowModalWithSize(UTKModal.ModalSize size) { if (_root == null) return; var modal = UTKModal.Show($"{size} Modal", size); modal.Add(new Label($"이것은 {size} 크기의 모달입니다.")); modal.OnClosed += () => Debug.Log($"{size} modal closed"); } #endregion #region Notification Initializers private void InitializeNotificationSample(VisualElement root) { if (_root == null) return; UTKNotification.SetRoot(_root); // Notification Types var btnInfo = root.Q("btn-noti-info"); btnInfo?.RegisterCallback(_ => UTKNotification.ShowInfo("정보", "이것은 정보 알림입니다.")); var btnSuccess = root.Q("btn-noti-success"); btnSuccess?.RegisterCallback(_ => UTKNotification.ShowSuccess("성공", "작업이 성공적으로 완료되었습니다!")); var btnWarning = root.Q("btn-noti-warning"); btnWarning?.RegisterCallback(_ => UTKNotification.ShowWarning("경고", "주의가 필요한 상황입니다.")); var btnError = root.Q("btn-noti-error"); btnError?.RegisterCallback(_ => UTKNotification.ShowError("오류", "오류가 발생했습니다!")); // Position var btnTopLeft = root.Q("btn-noti-top-left"); btnTopLeft?.RegisterCallback(_ => UTKNotification.Show("Top Left", "TopLeft 위치 알림", UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.TopLeft)); var btnTopRight = root.Q("btn-noti-top-right"); btnTopRight?.RegisterCallback(_ => UTKNotification.Show("Top Right", "TopRight 위치 알림", UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.TopRight)); var btnBottomLeft = root.Q("btn-noti-bottom-left"); btnBottomLeft?.RegisterCallback(_ => UTKNotification.Show("Bottom Left", "BottomLeft 위치 알림", UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.BottomLeft)); var btnBottomRight = root.Q("btn-noti-bottom-right"); btnBottomRight?.RegisterCallback(_ => UTKNotification.Show("Bottom Right", "BottomRight 위치 알림", UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.BottomRight)); // With Actions var btnAction = root.Q("btn-noti-action"); btnAction?.RegisterCallback(_ => { var notification = UTKNotification.Show("업데이트 가능", "새로운 버전이 있습니다. 업데이트하시겠습니까?", UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.TopRight); notification.AddAction("업데이트", "update"); notification.AddAction("나중에", "later"); notification.OnActionClicked += (actionId) => { Debug.Log($"Action clicked: {actionId}"); }; }); var btnPersistent = root.Q("btn-noti-persistent"); btnPersistent?.RegisterCallback(_ => { var notification = UTKNotification.Show("수동 닫기", "이 알림은 자동으로 닫히지 않습니다. X 버튼을 눌러 닫아주세요.", UTKNotification.NotificationType.Warning, UTKNotification.NotificationPosition.TopRight, duration: 0); notification.OnClosed += () => Debug.Log("Persistent notification closed"); }); SetCodeSamples(root, csharpCode: @"// Root 설정 (한 번만) UTKNotification.SetRoot(rootVisualElement); // ======================================== // 1. 기본 알림 타입 // ======================================== // Info UTKNotification.ShowInfo(""정보"", ""이것은 정보 알림입니다.""); // Success UTKNotification.ShowSuccess(""성공"", ""작업이 완료되었습니다!""); // Warning UTKNotification.ShowWarning(""경고"", ""주의가 필요합니다.""); // Error UTKNotification.ShowError(""오류"", ""오류가 발생했습니다!""); // ======================================== // 2. 위치 지정 // ======================================== UTKNotification.Show(""제목"", ""메시지"", UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.TopRight); // 기본값 UTKNotification.Show(""제목"", ""메시지"", UTKNotification.NotificationType.Success, UTKNotification.NotificationPosition.BottomLeft); // ======================================== // 3. 지속 시간 설정 // ======================================== // 기본 5초 UTKNotification.ShowInfo(""정보"", ""5초 후 자동 닫힘""); // 10초 UTKNotification.ShowInfo(""정보"", ""10초 후 자동 닫힘"", duration: 10000); // 수동 닫기 (자동 닫힘 없음) UTKNotification.ShowWarning(""경고"", ""수동으로 닫아주세요."", duration: 0); // ======================================== // 4. 액션 버튼 추가 // ======================================== var notification = UTKNotification.Show( ""업데이트 가능"", ""새로운 버전이 있습니다."", UTKNotification.NotificationType.Info, UTKNotification.NotificationPosition.TopRight); notification.AddAction(""업데이트"", ""update""); notification.AddAction(""나중에"", ""later""); notification.OnActionClicked += (actionId) => { if (actionId == ""update"") Debug.Log(""업데이트 시작""); else Debug.Log(""나중에 업데이트""); }; // ======================================== // 5. 닫힘 이벤트 // ======================================== var noti = UTKNotification.ShowInfo(""알림"", ""메시지""); noti.OnClosed += () => Debug.Log(""알림이 닫혔습니다.""); // ======================================== // 6. 인스턴스 직접 생성 // ======================================== var custom = new UTKNotification(""제목"", ""메시지"", UTKNotification.NotificationType.Success); custom.Duration = 0; custom.AddAction(""확인"", ""confirm""); rootVisualElement.Add(custom);"); } #endregion #region Picker Initializers private void InitializeColorPickerSample(VisualElement root) { if (_root == null) return; UTKColorPicker.SetRoot(_root); _colorPreviewBox = root.Q("color-preview-box"); _colorHexLabel = root.Q