Files
crtr/Assets/Cryville/Crtr/Browsing/UI/PathedResourceBrowser.cs

192 lines
5.0 KiB
C#

using Cryville.Common.Unity.UI;
using Cryville.Crtr.Browsing.Actions;
using Cryville.Crtr.UI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Cryville.Crtr.Browsing.UI {
internal class PathedResourceBrowser : ResourceBrowser {
[SerializeField]
Button[] m_writeTools;
[SerializeField]
TextMeshProUGUI m_pathText;
[SerializeField]
ScrollableItemGrid m_itemContainer;
[SerializeField]
DetailPanel m_detailPanel;
[SerializeField]
ActionBar m_actionBar;
[SerializeField]
Sprite m_readonlyIcon;
public override Sprite Icon {
get {
return _manager.IsReadOnly ? m_readonlyIcon : base.Icon;
}
}
IPathedResourceManager<IResourceMeta> _manager;
IResourceAction _importAction;
readonly IResourceAction[] _importActionArray = new IResourceAction[1];
readonly HashSet<int> _selectedItems = new();
readonly Dictionary<int, BrowserItem> _items = new();
bool _destroyed;
protected virtual void Start() {
m_itemContainer.LoadItem = LoadItem;
}
void OnDestroy() {
_destroyed = true;
UnregisterManager();
}
void UnregisterManager() {
if (_importAction != null) Master.Actions.Unregister(_importAction);
_manager.ItemChanged -= OnItemChanged;
_manager.DirectoryChanged -= OnDirectoryChanged;
}
void OnEnable() {
_manager?.Activate();
}
void OnDisable() {
_manager?.Deactivate();
}
public void Init(IPathedResourceManager<IResourceMeta> manager) {
if (_manager != null) {
OnDisable();
UnregisterManager();
}
_manager = manager;
_manager.ItemChanged += OnItemChanged;
_manager.DirectoryChanged += OnDirectoryChanged;
if (!_manager.IsReadOnly) {
Master.Actions.Register(_importAction = _manager.GetImportAction());
_importActionArray[0] = _importAction;
}
foreach (var tool in m_writeTools) tool.interactable = !_manager.IsReadOnly;
OnEnable();
OnItemChanged();
OnDirectoryChanged();
}
bool _itemChanged;
void OnItemChanged() {
_itemChanged = true;
}
void OnDirectoryChanged() {
if (_manager.CurrentDirectory.Count == 0) m_pathText.text = "(Home)";
else m_pathText.text = string.Join(Path.DirectorySeparatorChar, _manager.CurrentDirectory);
}
void Update() {
if (_itemChanged) {
_itemChanged = false;
_selectedItems.Clear();
_items.Clear();
m_itemContainer.ItemCount = _manager.Count;
m_detailPanel.Clear();
m_actionBar.Clear();
}
}
private bool LoadItem(int id, GameObject obj) {
var bi = obj.GetComponent<BrowserItem>();
_items[id] = bi;
try {
var item = _manager[id];
bi.Load(this, id, _manager.IsDirectory(id), item, _selectedItems.Contains(id));
}
catch (Exception) {
bi.Load(this, id, _manager.IsDirectory(id), null, _selectedItems.Contains(id));
}
return true;
}
public override void OnItemClicked(int id) {
if (_manager.IsDirectory(id)) {
_manager.OpenDirectory(id);
}
else {
foreach (var item in _selectedItems) _items[item].OnDeselect();
_selectedItems.Clear();
_items[id].OnSelect();
_selectedItems.Add(id);
try {
var res = _manager[id];
m_detailPanel.Load(res);
if (_selectedItems.Count == 1) {
LoadActions(_manager.GetItemUri(id), res);
}
}
catch (Exception ex) {
Popup.CreateException(ex);
}
}
}
internal override void OnActionsChanged() {
if (_destroyed) return;
if (_selectedItems.Count == 1) {
int id = _selectedItems.Single();
LoadActions(_manager.GetItemUri(id), _manager[id]);
}
}
void LoadActions(Uri uri, IResourceMeta res) {
m_actionBar.Load(this, Master.Actions.GetActions(uri, res).Except(_importActionArray));
}
public void OnPathClicked(int index) {
_manager.ReturnToDirectory(index);
}
public void OnHomeClicked() {
_manager.ChangeDirectory(Enumerable.Empty<string>());
}
public void OnParentClicked() {
var depth = _manager.CurrentDirectory.Count;
if (depth <= 0) return;
_manager.ReturnToDirectory(_manager.CurrentDirectory.Count - 2);
}
public void OnSearch(string value) {
_manager.ApplyFilter(value);
}
public void OnDeleteClicked() {
if (_selectedItems.Count == 0) {
Popup.Create("No item is selected.");
return;
}
Dialog.Show(DeleteSelectedItems, "Are you sure to delete the selected item(s)?", "Yes", "No");
}
void DeleteSelectedItems(int result) {
if (result != 0) return;
foreach (var item in _selectedItems.OrderByDescending(i => i)) _manager.RemoveAt(item);
}
public override void InvokeAction(IResourceAction action) {
if (_selectedItems.Count == 0) {
Popup.Create("No item is selected.");
return;
}
if (_selectedItems.Count > 1) {
Popup.Create("Cannot run this action with multiple items.");
return;
}
foreach (var i in _selectedItems) {
try {
action.Invoke(_manager.GetItemUri(i), _manager[i]);
}
catch (Exception ex) {
Dialog.Show(null, ex.Message);
Game.MainLogger.Log(4, "Config", "An error occurred while running the action: {0}", ex);
}
}
}
}
}