Penumbra/Penumbra/UI/CollectionTab/CollectionSelector.cs
Ottermandias 97c8d82b33
Some checks failed
.NET Build / build (push) Has been cancelled
Prevent default-named collection from being renamed and always put it at the top of the selector.
2025-09-07 10:45:28 +02:00

145 lines
5.1 KiB
C#

using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using Penumbra.Collections;
using Penumbra.Collections.Manager;
using Penumbra.Communication;
using Penumbra.GameData.Actors;
using Penumbra.Services;
using Penumbra.UI.Classes;
namespace Penumbra.UI.CollectionTab;
public sealed class CollectionSelector : ItemSelector<ModCollection>, IDisposable
{
private readonly Configuration _config;
private readonly CommunicatorService _communicator;
private readonly CollectionStorage _storage;
private readonly ActiveCollections _active;
private readonly TutorialService _tutorial;
private readonly IncognitoService _incognito;
private ModCollection? _dragging;
public CollectionSelector(Configuration config, CommunicatorService communicator, CollectionStorage storage, ActiveCollections active,
TutorialService tutorial, IncognitoService incognito)
: base([], Flags.Delete | Flags.Add | Flags.Duplicate | Flags.Filter)
{
_config = config;
_communicator = communicator;
_storage = storage;
_active = active;
_tutorial = tutorial;
_incognito = incognito;
_communicator.CollectionChange.Subscribe(OnCollectionChange, CollectionChange.Priority.CollectionSelector);
// Set items.
OnCollectionChange(CollectionType.Inactive, null, null, string.Empty);
// Set selection.
OnCollectionChange(CollectionType.Current, null, _active.Current, string.Empty);
}
protected override bool OnDelete(int idx)
{
if (idx < 0 || idx >= Items.Count)
return false;
// Always return false since we handle the selection update ourselves.
_storage.RemoveCollection(Items[idx]);
return false;
}
protected override bool DeleteButtonEnabled()
=> _storage.DefaultNamed != Current && _config.DeleteModModifier.IsActive();
protected override string DeleteButtonTooltip()
=> _storage.DefaultNamed == Current
? $"The selected collection {Name(Current)} can not be deleted."
: $"Delete the currently selected collection {(Current != null ? Name(Current) : string.Empty)}. Hold {_config.DeleteModModifier} to delete.";
protected override bool OnAdd(string name)
=> _storage.AddCollection(name, null);
protected override bool OnDuplicate(string name, int idx)
{
if (idx < 0 || idx >= Items.Count)
return false;
return _storage.AddCollection(name, Items[idx]);
}
protected override bool Filtered(int idx)
=> !Items[idx].Identity.Name.Contains(Filter, StringComparison.OrdinalIgnoreCase);
private const string PayloadString = "Collection";
protected override bool OnDraw(int idx)
{
using var color = ImRaii.PushColor(ImGuiCol.Header, ColorId.SelectedCollection.Value());
var ret = ImGui.Selectable(Name(Items[idx]), idx == CurrentIdx);
using var source = ImRaii.DragDropSource();
if (idx == CurrentIdx)
_tutorial.OpenTutorial(BasicTutorialSteps.CurrentCollection);
if (source)
{
_dragging = Items[idx];
ImGui.SetDragDropPayload(PayloadString, null, 0);
ImGui.TextUnformatted($"Assigning {Name(_dragging)} to...");
}
if (ret)
_active.SetCollection(Items[idx], CollectionType.Current);
return ret;
}
public void DragTargetAssignment(CollectionType type, ActorIdentifier identifier)
{
using var target = ImRaii.DragDropTarget();
if (!target.Success || _dragging == null || !ImGuiUtil.IsDropping(PayloadString))
return;
_active.SetCollection(_dragging, type, _active.Individuals.GetGroup(identifier));
_dragging = null;
}
public void Dispose()
{
_communicator.CollectionChange.Unsubscribe(OnCollectionChange);
}
private string Name(ModCollection collection)
=> _incognito.IncognitoMode || collection.Identity.Name.Length == 0 ? collection.Identity.AnonymizedName : collection.Identity.Name;
public void RestoreCollections()
{
Items.Clear();
Items.Add(_storage.DefaultNamed);
foreach (var c in _storage.OrderBy(c => c.Identity.Name).Where(c => c != _storage.DefaultNamed))
Items.Add(c);
SetFilterDirty();
SetCurrent(_active.Current);
}
private void OnCollectionChange(CollectionType type, ModCollection? old, ModCollection? @new, string _3)
{
switch (type)
{
case CollectionType.Temporary: return;
case CollectionType.Current:
if (@new != null)
SetCurrent(@new);
SetFilterDirty();
return;
case CollectionType.Inactive:
RestoreCollections();
SetFilterDirty();
return;
default:
SetFilterDirty();
return;
}
}
}