UTKTopMenu 기능 추가

This commit is contained in:
logonkhi
2026-02-19 10:43:52 +09:00
parent 200a7faa6b
commit 0333b83b57
9 changed files with 457 additions and 50 deletions

View File

@@ -4,7 +4,6 @@ using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UIToolkit;
using UVC.UIToolkit.Menu;
using UVC.UI.Commands;
using UVC.Log;
@@ -24,12 +23,15 @@ namespace UVC.Sample.UIToolkit
private UTKToggle? _themeToggle;
private VisualElement? _root;
private UTKTopMenuView? _menuView;
private UTKTopMenu? _menuView;
private UTKTopMenuModel? _menuModel;
private UTKTopMenuView? _menuView2;
private UTKTopMenu? _menuView2;
private UTKTopMenuModel? _menuModel2;
private UTKTopMenu? _menuView3;
private UTKTopMenuModel? _menuModel3;
// 상태 관리용
private bool _canUndo = false;
private bool _canRedo = false;
@@ -72,12 +74,12 @@ namespace UVC.Sample.UIToolkit
if (_root == null) return;
// 1. UTKTopMenuView 생성
_menuView = new UTKTopMenuView();
_menuView = new UTKTopMenu();
_menuView.style.position = Position.Absolute;
_menuView.style.top = 0;
_menuView.style.left = 50;
_menuView2 = new UTKTopMenuView();
_menuView2 = new UTKTopMenu();
_menuView2.style.position = Position.Absolute;
_menuView2.style.top = 0;
_menuView2.style.left = 0;
@@ -85,10 +87,23 @@ namespace UVC.Sample.UIToolkit
_root.Add(_menuView2);
_root.Add(_menuView);
// 세로 정렬 메뉴 (Vertical Orientation + ItemSpacing)
_menuView3 = new UTKTopMenu();
_menuView3.Orientation = UTKMenuOrientation.Vertical;
_menuView3.ItemSpacing = 4f;
_menuView3.SubMenuOffsetX = -10f;
_menuView3.SubMenuOffsetY = 4f;
_menuView3.style.position = Position.Absolute;
_menuView3.style.top = 50;
_menuView3.style.left = 0;
_menuView3.style.width = 120;
_root.Add(_menuView3);
// 2. UTKTopMenuModel 생성 및 메뉴 아이템 추가
_menuModel = new UTKTopMenuModel();
_menuModel2 = new UTKTopMenuModel();
_menuModel3 = new UTKTopMenuModel();
CreateMenuItems();
// 3. View에 메뉴 생성
@@ -102,9 +117,15 @@ namespace UVC.Sample.UIToolkit
_menuView2.CreateMenuItems(_menuModel2.MenuItems, _menuView2.MenuContainer);
}
if (_menuView3.MenuContainer != null)
{
_menuView3.CreateMenuItems(_menuModel3.MenuItems, _menuView3.MenuContainer);
}
// 4. 이벤트 구독
_menuView.OnMenuItemClicked += HandleMenuItemClicked;
_menuView2.OnMenuItemClicked += HandleMenuItemClicked2;
_menuView3.OnMenuItemClicked += HandleMenuItemClicked3;
// 5. 상태 테스트 버튼 생성
CreateTestButtons();
@@ -117,7 +138,7 @@ namespace UVC.Sample.UIToolkit
/// </summary>
private void CreateMenuItems()
{
if (_menuModel == null || _menuModel2 == null) return;
if (_menuModel == null || _menuModel2 == null || _menuModel3 == null) return;
// 파일 메뉴
var fileMenu = new UTKMenuItemData("file", "파일");
@@ -264,7 +285,28 @@ namespace UVC.Sample.UIToolkit
_menuModel2.AddMenuItem(imageMenu);
ULog.Debug($"메뉴 아이템 생성 완료: {_menuModel.MenuItems.Count}개 최상위 메뉴");
// === 세로 메뉴 (menuView3) ===
var vertFileMenu = new UTKMenuItemData("v_file", "파일");
vertFileMenu.AddSubMenuItem(new UTKMenuItemData("v_file_new", "새 파일", new DebugLogCommand("세로 메뉴: 새 파일"), shortcut: "Ctrl+N"));
vertFileMenu.AddSubMenuItem(new UTKMenuItemData("v_file_open", "열기", new DebugLogCommand("세로 메뉴: 열기"), shortcut: "Ctrl+O"));
vertFileMenu.AddSubMenuItem(UTKMenuItemData.CreateSeparator());
vertFileMenu.AddSubMenuItem(new UTKMenuItemData("v_file_save", "저장", new DebugLogCommand("세로 메뉴: 저장"), shortcut: "Ctrl+S"));
_menuModel3.AddMenuItem(vertFileMenu);
var vertEditMenu = new UTKMenuItemData("v_edit", "편집");
vertEditMenu.AddSubMenuItem(new UTKMenuItemData("v_edit_undo", "실행 취소", new DebugLogCommand("세로 메뉴: 실행 취소"), shortcut: "Ctrl+Z"));
vertEditMenu.AddSubMenuItem(new UTKMenuItemData("v_edit_redo", "다시 실행", new DebugLogCommand("세로 메뉴: 다시 실행"), shortcut: "Ctrl+Y"));
_menuModel3.AddMenuItem(vertEditMenu);
var vertViewMenu = new UTKMenuItemData("v_view", "보기");
vertViewMenu.AddSubMenuItem(new UTKMenuItemData("v_view_fullscreen", "전체 화면", new DebugLogCommand("세로 메뉴: 전체 화면"), shortcut: "F11"));
_menuModel3.AddMenuItem(vertViewMenu);
var vertHelpMenu = new UTKMenuItemData("v_help", "도움말");
vertHelpMenu.AddSubMenuItem(new UTKMenuItemData("v_help_about", "정보", new DebugLogCommand("세로 메뉴: 정보")));
_menuModel3.AddMenuItem(vertHelpMenu);
ULog.Debug($"메뉴 아이템 생성 완료: {_menuModel.MenuItems.Count}개 최상위 메뉴, 세로 메뉴: {_menuModel3.MenuItems.Count}개");
}
/// <summary>
@@ -278,7 +320,7 @@ namespace UVC.Sample.UIToolkit
var buttonContainer = new VisualElement();
buttonContainer.style.position = Position.Absolute;
buttonContainer.style.top = 60;
buttonContainer.style.left = 10;
buttonContainer.style.left = 300;
buttonContainer.style.flexDirection = FlexDirection.Column;
buttonContainer.style.width = 250;
_root.Insert(0, buttonContainer);
@@ -335,8 +377,25 @@ namespace UVC.Sample.UIToolkit
{
text = "Save 단축키 변경"
};
changeShortcutBtn.style.marginBottom = 5;
buttonContainer.Add(changeShortcutBtn);
// ExecuteCommand 테스트
var executeCommandBtn = new Button(() => TestExecuteCommand())
{
text = "ExecuteCommand 테스트"
};
executeCommandBtn.style.marginBottom = 5;
buttonContainer.Add(executeCommandBtn);
// TryGetMenuItemData 테스트
var getDataBtn = new Button(() => TestTryGetMenuItemData())
{
text = "TryGetMenuItemData 테스트"
};
getDataBtn.style.marginBottom = 5;
buttonContainer.Add(getDataBtn);
// 상태 표시 레이블
var statusLabel = new Label();
statusLabel.style.marginTop = 20;
@@ -501,6 +560,51 @@ namespace UVC.Sample.UIToolkit
label.schedule.Execute(() => UpdateStatusLabel(label)).Every(100);
}
/// <summary>
/// ExecuteCommand 테스트: ItemId로 Command를 직접 실행합니다.
/// </summary>
private void TestExecuteCommand()
{
if (_menuView == null) return;
// file_new는 항상 활성화 → true 반환
bool result1 = _menuView.ExecuteCommand("file_new");
ULog.Debug($"ExecuteCommand(\"file_new\"): {result1}");
// file_save는 비활성화 시 false 반환
bool result2 = _menuView.ExecuteCommand("file_save");
ULog.Debug($"ExecuteCommand(\"file_save\"): {result2} (비활성화 상태이면 false)");
// 존재하지 않는 ID → false 반환
bool result3 = _menuView.ExecuteCommand("not_exist");
ULog.Debug($"ExecuteCommand(\"not_exist\"): {result3}");
}
/// <summary>
/// TryGetMenuItemData 테스트: ItemId로 메뉴 데이터를 조회합니다.
/// </summary>
private void TestTryGetMenuItemData()
{
if (_menuView == null) return;
if (_menuView.TryGetMenuItemData("file_save", out var data))
{
ULog.Debug($"TryGetMenuItemData(\"file_save\"): " +
$"DisplayName={data?.DisplayName}, " +
$"IsEnabled={data?.IsEnabled}, " +
$"Shortcut={data?.Shortcut}, " +
$"HasCommand={data?.Command != null}");
}
else
{
ULog.Debug("TryGetMenuItemData(\"file_save\"): 찾을 수 없음");
}
// 존재하지 않는 ID
bool found = _menuView.TryGetMenuItemData("not_exist", out _);
ULog.Debug($"TryGetMenuItemData(\"not_exist\"): {found}");
}
/// <summary>
/// 메뉴 아이템 클릭 핸들러입니다.
/// </summary>
@@ -530,6 +634,21 @@ namespace UVC.Sample.UIToolkit
}
}
/// <summary>
/// 세로 메뉴 클릭 핸들러입니다.
/// </summary>
private void HandleMenuItemClicked3(UTKMenuItemData itemData)
{
if (itemData == null) return;
ULog.Debug($"세로 메뉴 클릭: {itemData.ItemId} - {itemData.DisplayName}");
if (itemData.Command != null)
{
itemData.Command.Execute(itemData.CommandParameter);
}
}
private void OnDestroy()
{
// 이벤트 구독 해제
@@ -539,8 +658,22 @@ namespace UVC.Sample.UIToolkit
_menuView.Dispose();
}
if (_menuView2 != null)
{
_menuView2.OnMenuItemClicked -= HandleMenuItemClicked2;
_menuView2.Dispose();
}
if (_menuView3 != null)
{
_menuView3.OnMenuItemClicked -= HandleMenuItemClicked3;
_menuView3.Dispose();
}
// 모델 정리
_menuModel?.Dispose();
_menuModel2?.Dispose();
_menuModel3?.Dispose();
ULog.Debug("UTKMenuSample 정리 완료");
}