344 lines
14 KiB
C#
344 lines
14 KiB
C#
using Dalamud.Interface;
|
|
using Dalamud.Interface.Utility;
|
|
using ImGuiNET;
|
|
using OtterGui;
|
|
using OtterGui.Raii;
|
|
using System;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using CustomizePlus.Profiles;
|
|
using CustomizePlus.Configuration.Data;
|
|
using CustomizePlus.Profiles.Data;
|
|
using CustomizePlus.UI.Windows.Controls;
|
|
using CustomizePlus.Templates;
|
|
using CustomizePlus.Core.Data;
|
|
using CustomizePlus.Templates.Events;
|
|
|
|
namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles;
|
|
|
|
public class ProfilePanel
|
|
{
|
|
private readonly ProfileFileSystemSelector _selector;
|
|
private readonly ProfileManager _manager;
|
|
private readonly PluginConfiguration _configuration;
|
|
private readonly TemplateCombo _templateCombo;
|
|
private readonly TemplateEditorManager _templateEditorManager;
|
|
private readonly TemplateEditorEvent _templateEditorEvent;
|
|
|
|
private string? _newName;
|
|
private string? _newCharacterName;
|
|
private Profile? _changedProfile;
|
|
|
|
private Action? _endAction;
|
|
|
|
private int _dragIndex = -1;
|
|
|
|
private string SelectionName
|
|
=> _selector.Selected == null ? "No Selection" : _selector.IncognitoMode ? _selector.Selected.Incognito : _selector.Selected.Name.Text;
|
|
|
|
public ProfilePanel(
|
|
ProfileFileSystemSelector selector,
|
|
ProfileManager manager,
|
|
PluginConfiguration configuration,
|
|
TemplateCombo templateCombo,
|
|
TemplateEditorManager templateEditorManager,
|
|
TemplateEditorEvent templateEditorEvent)
|
|
{
|
|
_selector = selector;
|
|
_manager = manager;
|
|
_configuration = configuration;
|
|
_templateCombo = templateCombo;
|
|
_templateEditorManager = templateEditorManager;
|
|
_templateEditorEvent = templateEditorEvent;
|
|
}
|
|
|
|
public void Draw()
|
|
{
|
|
using var group = ImRaii.Group();
|
|
if (_selector.SelectedPaths.Count > 1)
|
|
{
|
|
DrawMultiSelection();
|
|
}
|
|
else
|
|
{
|
|
DrawHeader();
|
|
DrawPanel();
|
|
}
|
|
}
|
|
|
|
private HeaderDrawer.Button LockButton()
|
|
=> _selector.Selected == null
|
|
? HeaderDrawer.Button.Invisible
|
|
: _selector.Selected.IsWriteProtected
|
|
? new HeaderDrawer.Button
|
|
{
|
|
Description = "Make this profile editable.",
|
|
Icon = FontAwesomeIcon.Lock,
|
|
OnClick = () => _manager.SetWriteProtection(_selector.Selected!, false)
|
|
}
|
|
: new HeaderDrawer.Button
|
|
{
|
|
Description = "Write-protect this profile.",
|
|
Icon = FontAwesomeIcon.LockOpen,
|
|
OnClick = () => _manager.SetWriteProtection(_selector.Selected!, true)
|
|
};
|
|
|
|
private void DrawHeader()
|
|
=> HeaderDrawer.Draw(SelectionName, 0, ImGui.GetColorU32(ImGuiCol.FrameBg),
|
|
0, LockButton(),
|
|
HeaderDrawer.Button.IncognitoButton(_selector.IncognitoMode, v => _selector.IncognitoMode = v));
|
|
|
|
private void DrawMultiSelection()
|
|
{
|
|
if (_selector.SelectedPaths.Count == 0)
|
|
return;
|
|
|
|
var sizeType = ImGui.GetFrameHeight();
|
|
var availableSizePercent = (ImGui.GetContentRegionAvail().X - sizeType - 4 * ImGui.GetStyle().CellPadding.X) / 100;
|
|
var sizeMods = availableSizePercent * 35;
|
|
var sizeFolders = availableSizePercent * 65;
|
|
|
|
ImGui.NewLine();
|
|
ImGui.TextUnformatted("Currently Selected Profiles");
|
|
ImGui.Separator();
|
|
using var table = ImRaii.Table("profile", 3, ImGuiTableFlags.RowBg);
|
|
ImGui.TableSetupColumn("btn", ImGuiTableColumnFlags.WidthFixed, sizeType);
|
|
ImGui.TableSetupColumn("name", ImGuiTableColumnFlags.WidthFixed, sizeMods);
|
|
ImGui.TableSetupColumn("path", ImGuiTableColumnFlags.WidthFixed, sizeFolders);
|
|
|
|
var i = 0;
|
|
foreach (var (fullName, path) in _selector.SelectedPaths.Select(p => (p.FullName(), p))
|
|
.OrderBy(p => p.Item1, StringComparer.OrdinalIgnoreCase))
|
|
{
|
|
using var id = ImRaii.PushId(i++);
|
|
ImGui.TableNextColumn();
|
|
var icon = (path is ProfileFileSystem.Leaf ? FontAwesomeIcon.FileCircleMinus : FontAwesomeIcon.FolderMinus).ToIconString();
|
|
if (ImGuiUtil.DrawDisabledButton(icon, new Vector2(sizeType), "Remove from selection.", false, true))
|
|
_selector.RemovePathFromMultiSelection(path);
|
|
|
|
ImGui.TableNextColumn();
|
|
ImGui.AlignTextToFramePadding();
|
|
ImGui.TextUnformatted(path is ProfileFileSystem.Leaf l ? _selector.IncognitoMode ? l.Value.Incognito : l.Value.Name.Text : string.Empty);
|
|
|
|
ImGui.TableNextColumn();
|
|
ImGui.AlignTextToFramePadding();
|
|
ImGui.TextUnformatted(_selector.IncognitoMode ? "Incognito is active" : fullName);
|
|
}
|
|
}
|
|
|
|
private void DrawPanel()
|
|
{
|
|
using var child = ImRaii.Child("##Panel", -Vector2.One, true);
|
|
if (!child || _selector.Selected == null)
|
|
return;
|
|
|
|
DrawEnabledSetting();
|
|
using (var disabled = ImRaii.Disabled(_selector.Selected?.IsWriteProtected ?? true))
|
|
{
|
|
DrawBasicSettings();
|
|
DrawTemplateArea();
|
|
}
|
|
}
|
|
|
|
private void DrawEnabledSetting()
|
|
{
|
|
var spacing = ImGui.GetStyle().ItemInnerSpacing with { X = ImGui.GetStyle().ItemSpacing.X, Y = ImGui.GetStyle().ItemSpacing.Y };
|
|
|
|
using (var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing))
|
|
{
|
|
var enabled = _selector.Selected?.Enabled ?? false;
|
|
using (ImRaii.Disabled(_templateEditorManager.IsEditorActive || _templateEditorManager.IsEditorPaused))
|
|
{
|
|
if (ImGui.Checkbox("##Enabled", ref enabled))
|
|
_manager.SetEnabled(_selector.Selected!, enabled);
|
|
ImGuiUtil.LabeledHelpMarker("Enabled",
|
|
"Whether the templates in this profile should be applied at all. Only one profile can be enabled for a character at the same time.");
|
|
}
|
|
|
|
ImGui.SameLine();
|
|
var isDefault = _manager.DefaultProfile == _selector.Selected;
|
|
var isDefaultOrCurrentProfilesEnabled = _manager.DefaultProfile?.Enabled ?? false || enabled;
|
|
using (ImRaii.Disabled(isDefaultOrCurrentProfilesEnabled))
|
|
{
|
|
if (ImGui.Checkbox("##DefaultProfile", ref isDefault))
|
|
_manager.SetDefaultProfile(isDefault ? _selector.Selected! : null);
|
|
ImGuiUtil.LabeledHelpMarker("Default profile (Players and Retainers only)",
|
|
"Whether the templates in this profile are applied to all players and retainers without a specific profile. Only one profile can be default at the same time.");
|
|
}
|
|
if(isDefaultOrCurrentProfilesEnabled)
|
|
{
|
|
ImGui.SameLine();
|
|
ImGui.PushStyleColor(ImGuiCol.Text, Constants.Colors.Warning);
|
|
ImGuiUtil.PrintIcon(FontAwesomeIcon.ExclamationTriangle);
|
|
ImGui.PopStyleColor();
|
|
ImGuiUtil.HoverTooltip("Can only be changed while currently selected and the default profiles are disabled.");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawBasicSettings()
|
|
{
|
|
using (var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f)))
|
|
{
|
|
using (var table = ImRaii.Table("BasicSettings", 2))
|
|
{
|
|
ImGui.TableSetupColumn("BasicCol1", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("lorem ipsum dolor").X);
|
|
ImGui.TableSetupColumn("BasicCol2", ImGuiTableColumnFlags.WidthStretch);
|
|
|
|
ImGuiUtil.DrawFrameColumn("Profile Name");
|
|
ImGui.TableNextColumn();
|
|
var width = new Vector2(ImGui.GetContentRegionAvail().X, 0);
|
|
var name = _newName ?? _selector.Selected!.Name;
|
|
ImGui.SetNextItemWidth(width.X);
|
|
|
|
if (!_selector.IncognitoMode)
|
|
{
|
|
if (ImGui.InputText("##ProfileName", ref name, 128))
|
|
{
|
|
_newName = name;
|
|
_changedProfile = _selector.Selected;
|
|
}
|
|
|
|
if (ImGui.IsItemDeactivatedAfterEdit() && _changedProfile != null)
|
|
{
|
|
_manager.Rename(_changedProfile, name);
|
|
_newName = null;
|
|
_changedProfile = null;
|
|
}
|
|
}
|
|
else
|
|
ImGui.TextUnformatted(_selector.Selected!.Incognito);
|
|
|
|
ImGui.TableNextRow();
|
|
|
|
ImGuiUtil.DrawFrameColumn("Character Name");
|
|
ImGui.TableNextColumn();
|
|
width = new Vector2(ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize("Limit to my creatures").X - 68, 0);
|
|
name = _newCharacterName ?? _selector.Selected!.CharacterName;
|
|
ImGui.SetNextItemWidth(width.X);
|
|
|
|
if (!_selector.IncognitoMode)
|
|
{
|
|
if (ImGui.InputText("##CharacterName", ref name, 128))
|
|
{
|
|
_newCharacterName = name;
|
|
_changedProfile = _selector.Selected;
|
|
}
|
|
|
|
if (ImGui.IsItemDeactivatedAfterEdit() && _changedProfile != null)
|
|
{
|
|
_manager.ChangeCharacterName(_changedProfile, name);
|
|
_newCharacterName = null;
|
|
_changedProfile = null;
|
|
}
|
|
}
|
|
else
|
|
ImGui.TextUnformatted("Incognito active");
|
|
|
|
ImGui.SameLine();
|
|
var enabled = _selector.Selected?.LimitLookupToOwnedObjects ?? false;
|
|
if (ImGui.Checkbox("##LimitLookupToOwnedObjects", ref enabled))
|
|
_manager.SetLimitLookupToOwned(_selector.Selected!, enabled);
|
|
ImGuiUtil.LabeledHelpMarker("Limit to my creatures",
|
|
"When enabled limits the character search to only your own summons, mounts and minions.\nUseful when there is possibility there will be another character with that name owned by another player.\n* For battle chocobo use \"Chocobo\" as character name.");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawTemplateArea()
|
|
{
|
|
using var table = ImRaii.Table("SetTable", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollX | ImGuiTableFlags.ScrollY);
|
|
if (!table)
|
|
return;
|
|
|
|
ImGui.TableSetupColumn("##del", ImGuiTableColumnFlags.WidthFixed, ImGui.GetFrameHeight());
|
|
ImGui.TableSetupColumn("##Index", ImGuiTableColumnFlags.WidthFixed, 30 * ImGuiHelpers.GlobalScale);
|
|
|
|
ImGui.TableSetupColumn("Template", ImGuiTableColumnFlags.WidthFixed, 220 * ImGuiHelpers.GlobalScale);
|
|
|
|
ImGui.TableSetupColumn("##editbtn", ImGuiTableColumnFlags.WidthFixed, 120 * ImGuiHelpers.GlobalScale);
|
|
|
|
ImGui.TableHeadersRow();
|
|
|
|
//warn: .ToList() might be performance critical at some point
|
|
//the copying via ToList is done because manipulations with .Templates list result in "Collection was modified" exception here
|
|
foreach (var (template, idx) in _selector.Selected!.Templates.WithIndex().ToList())
|
|
{
|
|
using var id = ImRaii.PushId(idx);
|
|
ImGui.TableNextColumn();
|
|
var keyValid = _configuration.UISettings.DeleteTemplateModifier.IsActive();
|
|
var tt = keyValid
|
|
? "Remove this template from the profile."
|
|
: $"Remove this template from the profile.\nHold {_configuration.UISettings.DeleteTemplateModifier} to remove.";
|
|
|
|
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), new Vector2(ImGui.GetFrameHeight()), tt, !keyValid, true))
|
|
_endAction = () => _manager.DeleteTemplate(_selector.Selected!, idx);
|
|
ImGui.TableNextColumn();
|
|
ImGui.Selectable($"#{idx + 1:D2}");
|
|
DrawDragDrop(_selector.Selected!, idx);
|
|
ImGui.TableNextColumn();
|
|
_templateCombo.Draw(_selector.Selected!, template, idx);
|
|
DrawDragDrop(_selector.Selected!, idx);
|
|
ImGui.TableNextColumn();
|
|
|
|
var disabledCondition = _templateEditorManager.IsEditorActive || template.IsWriteProtected;
|
|
using (var disabled = ImRaii.Disabled(disabledCondition))
|
|
{
|
|
if (ImGui.Button("Open in editor"))
|
|
_templateEditorEvent.Invoke(TemplateEditorEvent.Type.EditorEnableRequested, template);
|
|
ImGuiUtil.HoverTooltip("Open this template in the template editor");
|
|
}
|
|
|
|
if(disabledCondition)
|
|
{
|
|
ImGui.SameLine();
|
|
ImGui.PushStyleColor(ImGuiCol.Text, Constants.Colors.Warning);
|
|
ImGuiUtil.PrintIcon(FontAwesomeIcon.ExclamationTriangle);
|
|
ImGui.PopStyleColor();
|
|
ImGuiUtil.HoverTooltip("Can not be edited because this template is either write protected or template editor is already enabled.");
|
|
}
|
|
}
|
|
|
|
ImGui.TableNextColumn();
|
|
ImGui.TableNextColumn();
|
|
ImGui.AlignTextToFramePadding();
|
|
ImGui.TextUnformatted("New");
|
|
ImGui.TableNextColumn();
|
|
_templateCombo.Draw(_selector.Selected!, null, -1);
|
|
ImGui.TableNextRow();
|
|
|
|
_endAction?.Invoke();
|
|
_endAction = null;
|
|
}
|
|
|
|
private void DrawDragDrop(Profile profile, int index)
|
|
{
|
|
const string dragDropLabel = "TemplateDragDrop";
|
|
using (var target = ImRaii.DragDropTarget())
|
|
{
|
|
if (target.Success && ImGuiUtil.IsDropping(dragDropLabel))
|
|
{
|
|
if (_dragIndex >= 0)
|
|
{
|
|
var idx = _dragIndex;
|
|
_endAction = () => _manager.MoveTemplate(profile, idx, index);
|
|
}
|
|
|
|
_dragIndex = -1;
|
|
}
|
|
}
|
|
|
|
using (var source = ImRaii.DragDropSource())
|
|
{
|
|
if (source)
|
|
{
|
|
ImGui.TextUnformatted($"Moving template #{index + 1:D2}...");
|
|
if (ImGui.SetDragDropPayload(dragDropLabel, nint.Zero, 0))
|
|
{
|
|
_dragIndex = index;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|