376 lines
12 KiB
C#
376 lines
12 KiB
C#
#nullable enable
|
|
using Cysharp.Threading.Tasks;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace UVC.UI.Tab
|
|
{
|
|
|
|
/// <summary>
|
|
/// 탭 시스템을 제어하는 컨트롤러 클래스입니다.
|
|
/// 설정 관리와 조정 역할만 담당하고, 실제 UI와 로딩은 TabView에서 처리합니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <b>사용 예제:</b>
|
|
/// 1. TabContentConfig 설정
|
|
/// 2. 컨트롤러 초기화
|
|
/// <code>
|
|
/// public class TabSetup : MonoBehaviour
|
|
/// {
|
|
/// [SerializeField]
|
|
/// protected TabController? tabController;
|
|
///
|
|
/// protected virtual void Awake()
|
|
/// {
|
|
/// if (tabController == null)
|
|
/// {
|
|
/// Debug.LogError("TabController가 설정되지 않았습니다.");
|
|
/// return;
|
|
/// }
|
|
///
|
|
/// // 코드로 탭 설정하기
|
|
/// SetupTabs();
|
|
/// }
|
|
///
|
|
/// private void SetupTabs()
|
|
/// {
|
|
/// // 1. TabConfig 설정
|
|
/// tabController?.AddTabConfig("AGV", "AGV", "Factory/Prefabs/UI/Tab/DraggableListContent", null, CreateAGVData(), true);
|
|
/// tabController?.AddTabConfig("ALARM", "ALARM", "Factory/Prefabs/UI/Tab/DraggableListContent", null, CreateAlarmData(), true);
|
|
///
|
|
/// // 2. 컨트롤러 초기화
|
|
/// tabController?.Initialize();
|
|
/// }
|
|
///
|
|
/// // 샘플 데이터 생성 메서드들
|
|
///
|
|
/// private object CreateAGVData()
|
|
/// {
|
|
/// Dictionary<string, string> updateData = new Dictionary<string, string>();
|
|
/// return updateData;
|
|
/// }
|
|
///
|
|
/// private object CreateAlarmData()
|
|
/// {
|
|
/// Dictionary<string, string> updateData = new Dictionary<string, string>();
|
|
/// return updateData;
|
|
/// }
|
|
/// }
|
|
/// </code>
|
|
/// </example>
|
|
public class TabController : MonoBehaviour
|
|
{
|
|
[Header("탭 설정")]
|
|
[Tooltip("탭 뷰 컴포넌트")]
|
|
[SerializeField] private TabView? tabView;
|
|
|
|
[Header("탭 컨텐츠")]
|
|
[Tooltip("시작 시 자동 초기화 여부")]
|
|
[SerializeField] private bool initializeOnStart = false;
|
|
|
|
[Tooltip("탭 설정 목록")]
|
|
[SerializeField] private TabContentConfig[] tabConfigs = new TabContentConfig[0];
|
|
|
|
[Tooltip("활성화 탭 버튼을 클릭 시 해당 탭 비활성화 할지 여부")]
|
|
[SerializeField] private bool togglableTab = false;
|
|
|
|
// 탭 모델
|
|
private TabModel? _tabModel;
|
|
|
|
// 초기화 여부
|
|
private bool _isInitialized = false;
|
|
|
|
// 코드로 추가된 탭 설정 저장
|
|
private List<TabContentConfig> _additionalTabConfigs = new List<TabContentConfig>();
|
|
|
|
// 탭 변경 이벤트
|
|
public event Action<int>? OnTabChanged;
|
|
|
|
private void Awake()
|
|
{
|
|
_tabModel = new TabModel(togglableTab);
|
|
if (initializeOnStart)
|
|
{
|
|
Initialize();
|
|
}
|
|
}
|
|
|
|
#region 코드 기반 탭 설정 관리
|
|
|
|
/// <summary>
|
|
/// 코드에서 탭 설정을 추가합니다.
|
|
/// </summary>
|
|
public bool AddTabConfig(string id, string name, string path, string iconPath = "", object? data = null, bool useLazyLoading = false)
|
|
{
|
|
if (_isInitialized)
|
|
{
|
|
Debug.LogWarning("탭 시스템이 이미 초기화되었습니다.");
|
|
return false;
|
|
}
|
|
|
|
var config = new TabContentConfig(id, name, path, iconPath, useLazyLoading, data);
|
|
_additionalTabConfigs.Add(config);
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 모든 탭 설정을 가져옵니다.
|
|
/// </summary>
|
|
public List<TabContentConfig> GetAllTabConfigs()
|
|
{
|
|
List<TabContentConfig> allConfigs = new List<TabContentConfig>();
|
|
|
|
// Inspector 설정 추가
|
|
foreach (var config in tabConfigs)
|
|
{
|
|
if (!string.IsNullOrEmpty(config.tabID) && !string.IsNullOrEmpty(config.contentPath))
|
|
{
|
|
allConfigs.Add(config);
|
|
}
|
|
}
|
|
|
|
// 코드로 추가된 설정 추가
|
|
allConfigs.AddRange(_additionalTabConfigs);
|
|
|
|
return allConfigs;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 탭 시스템 초기화 및 관리
|
|
|
|
/// <summary>
|
|
/// 탭 시스템을 초기화합니다.
|
|
/// </summary>
|
|
public void Initialize()
|
|
{
|
|
if (_isInitialized || _tabModel == null || tabView == null)
|
|
return;
|
|
|
|
// 탭 모델 초기화
|
|
InitializeModel();
|
|
|
|
// TabView에 설정 전달하여 초기화
|
|
List<TabContentConfig> allConfigs = GetAllTabConfigs();
|
|
tabView.InitializeTabs(_tabModel.Tabs, allConfigs, OnTabButtonSelected, togglableTab);
|
|
|
|
// 모델 이벤트 구독
|
|
_tabModel.OnTabChanged += HandleTabChanged;
|
|
|
|
// 초기 탭 활성화
|
|
if (_tabModel.Tabs.Count > 0)
|
|
{
|
|
HandleTabChanged(_tabModel.ActiveTabIndex);
|
|
}
|
|
|
|
_isInitialized = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 탭 모델을 초기화합니다.
|
|
/// </summary>
|
|
private void InitializeModel()
|
|
{
|
|
if (_tabModel == null) return;
|
|
|
|
List<TabContentConfig> allConfigs = GetAllTabConfigs();
|
|
|
|
foreach (var config in allConfigs)
|
|
{
|
|
_tabModel.AddTab(new TabData(
|
|
config.tabID,
|
|
config.tabName,
|
|
config.contentPath,
|
|
config.tabIconPath,
|
|
config.initialData
|
|
));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 탭 버튼 선택 이벤트 처리
|
|
/// </summary>
|
|
private void OnTabButtonSelected(int tabIndex)
|
|
{
|
|
_tabModel?.SwitchToTab(tabIndex);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 탭 변경 이벤트 처리
|
|
/// </summary>
|
|
private void HandleTabChanged(int newTabIndex, object? updateData = null)
|
|
{
|
|
if (_tabModel == null || tabView == null) return;
|
|
|
|
TabData? activeTabData = null;
|
|
if (newTabIndex > -1)
|
|
{
|
|
activeTabData = _tabModel.GetActiveTab();
|
|
if (activeTabData == null) return;
|
|
}
|
|
|
|
// TabView에 탭 변경 전달
|
|
tabView.UpdateActiveTab(newTabIndex, _tabModel.PrevTabIndex, activeTabData, updateData).ContinueWith(() =>
|
|
{
|
|
// 외부 이벤트 발생
|
|
OnTabChanged?.Invoke(newTabIndex);
|
|
});
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 탭 활성화 및 데이터 관리
|
|
|
|
/// <summary>
|
|
/// ID로 특정 탭을 활성화합니다.
|
|
/// </summary>
|
|
/// <param name="tabID">활성화할 탭의 ID</param>
|
|
/// <param name="updateData">탭에 전달할 데이터 (선택적)</param>
|
|
public void ActivateTab(string tabID, object? updateData = null)
|
|
{
|
|
_tabModel?.SwitchToTab(tabID, updateData);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 인덱스로 특정 탭을 활성화합니다.
|
|
/// </summary>
|
|
/// <param name="tabIndex">활성화할 탭의 인덱스</param>
|
|
/// <param name="updateData">탭에 전달할 데이터 (선택적)</param>
|
|
public void ActivateTab(int tabIndex, object? updateData = null)
|
|
{
|
|
_tabModel?.SwitchToTab(tabIndex, updateData);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 현재 활성화된 탭 인덱스를 반환합니다.
|
|
/// </summary>
|
|
public int GetActiveTabIndex()
|
|
{
|
|
return _tabModel?.ActiveTabIndex ?? -1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 현재 활성화된 탭의 ID를 반환합니다.
|
|
/// </summary>
|
|
public string? GetActiveTabID()
|
|
{
|
|
TabData? activeTab = _tabModel?.GetActiveTab();
|
|
return activeTab?.tabID;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 현재 활성화된 탭의 ITabContent를 반환합니다.
|
|
/// </summary>
|
|
/// <returns>활성화된 탭의 ITabContent, 없으면 null</returns>
|
|
public ITabContent? GetActiveITabContent()
|
|
{
|
|
string? activeTabID = GetActiveTabID();
|
|
if (string.IsNullOrEmpty(activeTabID)) return null;
|
|
|
|
GameObject? tabInstance = GetTabInstance(activeTabID);
|
|
if (tabInstance == null) return null;
|
|
return tabInstance.GetComponent<ITabContent>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 탭의 데이터를 설정하고 갱신합니다.
|
|
/// </summary>
|
|
public void SetTabContentData(string tabID, object? data)
|
|
{
|
|
if (_tabModel == null || tabView == null) return;
|
|
|
|
// 모델 업데이트
|
|
_tabModel.UpdateTabContentData(tabID, data);
|
|
|
|
// TabView에 업데이트 전달
|
|
int tabIndex = GetTabIndexByID(tabID);
|
|
if (tabIndex >= 0)
|
|
{
|
|
tabView.UpdateTabContentData(tabIndex, data);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 탭 ID로 인덱스를 찾습니다.
|
|
/// </summary>
|
|
private int GetTabIndexByID(string tabID)
|
|
{
|
|
if (_tabModel != null)
|
|
{
|
|
for (int i = 0; i < _tabModel.Tabs.Count; i++)
|
|
{
|
|
if (_tabModel.Tabs[i].tabID == tabID)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region TabView 위임 메서드
|
|
|
|
/// <summary>
|
|
/// 특정 탭의 컨텐츠 인스턴스를 가져옵니다.
|
|
/// </summary>
|
|
public GameObject? GetTabInstance(string tabID, bool autoLoad = false)
|
|
{
|
|
return tabView?.GetTabInstance(tabID, autoLoad);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 탭의 컴포넌트를 가져옵니다.
|
|
/// </summary>
|
|
public T? GetTabComponent<T>(string tabID, bool autoLoad = false) where T : Component
|
|
{
|
|
return tabView?.GetTabComponent<T>(tabID, autoLoad);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 탭이 로드되었는지 확인합니다.
|
|
/// </summary>
|
|
public bool IsTabLoaded(string tabID)
|
|
{
|
|
return tabView?.IsTabLoaded(tabID) ?? false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 현재 활성화된 탭을 제외한 모든 지연 로드 탭을 언로드합니다.
|
|
/// </summary>
|
|
public void UnloadAllExceptCurrent()
|
|
{
|
|
int currentIndex = GetActiveTabIndex();
|
|
tabView?.UnloadAllExceptCurrent(currentIndex);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 탭의 컨텐츠를 언로드합니다.
|
|
/// </summary>
|
|
public bool UnloadTabContent(string tabID)
|
|
{
|
|
return tabView?.UnloadTabContent(tabID) ?? false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 모든 탭 컨텐츠를 미리 로드합니다.
|
|
/// </summary>
|
|
public void PreloadAllTabs()
|
|
{
|
|
tabView?.PreloadAllTabs();
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (_tabModel != null)
|
|
{
|
|
_tabModel.OnTabChanged -= HandleTabChanged;
|
|
}
|
|
}
|
|
}
|
|
} |