mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-20 23:07:51 +01:00
More future proof structure for tags.
This commit is contained in:
parent
52c1708dd2
commit
0e50a8a9e5
4 changed files with 47 additions and 45 deletions
|
|
@ -29,7 +29,7 @@ public class ModPanelDescriptionTab(
|
||||||
ImGui.Dummy(ImGuiHelpers.ScaledVector2(2));
|
ImGui.Dummy(ImGuiHelpers.ScaledVector2(2));
|
||||||
|
|
||||||
ImGui.Dummy(ImGuiHelpers.ScaledVector2(2));
|
ImGui.Dummy(ImGuiHelpers.ScaledVector2(2));
|
||||||
var (predefinedTagsEnabled, predefinedTagButtonOffset) = predefinedTagsConfig.PredefinedTags.Count > 0
|
var (predefinedTagsEnabled, predefinedTagButtonOffset) = predefinedTagsConfig.Count > 0
|
||||||
? (true, ImGui.GetFrameHeight() + ImGui.GetStyle().WindowPadding.X + (ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ScrollbarSize : 0))
|
? (true, ImGui.GetFrameHeight() + ImGui.GetStyle().WindowPadding.X + (ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ScrollbarSize : 0))
|
||||||
: (false, 0);
|
: (false, 0);
|
||||||
var tagIdx = _localTags.Draw("Local Tags: ",
|
var tagIdx = _localTags.Draw("Local Tags: ",
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ public class ModPanelEditTab(
|
||||||
}
|
}
|
||||||
|
|
||||||
UiHelpers.DefaultLineSpace();
|
UiHelpers.DefaultLineSpace();
|
||||||
var sharedTagsEnabled = predefinedTagManager.PredefinedTags.Count > 0;
|
var sharedTagsEnabled = predefinedTagManager.Count > 0;
|
||||||
var sharedTagButtonOffset = sharedTagsEnabled ? ImGui.GetFrameHeight() + ImGui.GetStyle().FramePadding.X : 0;
|
var sharedTagButtonOffset = sharedTagsEnabled ? ImGui.GetFrameHeight() + ImGui.GetStyle().FramePadding.X : 0;
|
||||||
var tagIdx = _modTags.Draw("Mod Tags: ", "Edit tags by clicking them, or add new tags. Empty tags are removed.", _mod.ModTags,
|
var tagIdx = _modTags.Draw("Mod Tags: ", "Edit tags by clicking them, or add new tags. Empty tags are removed.", _mod.ModTags,
|
||||||
out var editedTag, rightEndOffset: sharedTagButtonOffset);
|
out var editedTag, rightEndOffset: sharedTagButtonOffset);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
|
|
@ -12,8 +13,13 @@ using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
|
||||||
|
|
||||||
namespace Penumbra.UI;
|
namespace Penumbra.UI;
|
||||||
|
|
||||||
public sealed class PredefinedTagManager : ISavable
|
public sealed class PredefinedTagManager : ISavable, IReadOnlyList<string>
|
||||||
{
|
{
|
||||||
|
public const int Version = 1;
|
||||||
|
|
||||||
|
public record struct TagData
|
||||||
|
{ }
|
||||||
|
|
||||||
private readonly ModManager _modManager;
|
private readonly ModManager _modManager;
|
||||||
private readonly SaveService _saveService;
|
private readonly SaveService _saveService;
|
||||||
|
|
||||||
|
|
@ -21,17 +27,7 @@ public sealed class PredefinedTagManager : ISavable
|
||||||
private uint _enabledColor;
|
private uint _enabledColor;
|
||||||
private uint _disabledColor;
|
private uint _disabledColor;
|
||||||
|
|
||||||
|
private readonly SortedList<string, TagData> _predefinedTags = [];
|
||||||
// Operations on this list assume that it is sorted and will keep it sorted if that is the case.
|
|
||||||
// The list also gets re-sorted when first loaded from config in case the config was modified.
|
|
||||||
[JsonRequired]
|
|
||||||
private readonly List<string> _predefinedTags = [];
|
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public IReadOnlyList<string> PredefinedTags
|
|
||||||
=> _predefinedTags;
|
|
||||||
|
|
||||||
public int ConfigVersion = 1;
|
|
||||||
|
|
||||||
public PredefinedTagManager(ModManager modManager, SaveService saveService)
|
public PredefinedTagManager(ModManager modManager, SaveService saveService)
|
||||||
{
|
{
|
||||||
|
|
@ -47,8 +43,12 @@ public sealed class PredefinedTagManager : ISavable
|
||||||
{
|
{
|
||||||
using var jWriter = new JsonTextWriter(writer);
|
using var jWriter = new JsonTextWriter(writer);
|
||||||
jWriter.Formatting = Formatting.Indented;
|
jWriter.Formatting = Formatting.Indented;
|
||||||
var serializer = new JsonSerializer { Formatting = Formatting.Indented };
|
var jObj = new JObject()
|
||||||
serializer.Serialize(jWriter, this);
|
{
|
||||||
|
["Version"] = Version,
|
||||||
|
["Tags"] = JObject.FromObject(_predefinedTags),
|
||||||
|
};
|
||||||
|
jObj.WriteTo(jWriter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
|
|
@ -61,48 +61,38 @@ public sealed class PredefinedTagManager : ISavable
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var text = File.ReadAllText(_saveService.FileNames.PredefinedTagFile);
|
var text = File.ReadAllText(_saveService.FileNames.PredefinedTagFile);
|
||||||
JsonConvert.PopulateObject(text, this, new JsonSerializerSettings
|
var jObj = JObject.Parse(text);
|
||||||
|
var version = jObj["Version"]?.ToObject<int>() ?? 0;
|
||||||
|
switch (version)
|
||||||
{
|
{
|
||||||
Error = HandleDeserializationError,
|
case 1:
|
||||||
});
|
var tags = jObj["Tags"]?.ToObject<Dictionary<string, TagData>>() ?? [];
|
||||||
|
foreach (var (tag, data) in tags)
|
||||||
// Any changes to this within this class should keep it sorted, but in case someone went in and manually changed the JSON, run a sort on initial load.
|
_predefinedTags.TryAdd(tag, data);
|
||||||
_predefinedTags.Sort();
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception($"Invalid version {version}.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Penumbra.Messager.NotificationMessage(ex,
|
Penumbra.Messager.NotificationMessage(ex,
|
||||||
"Error reading shared tags Configuration, reverting to default.",
|
"Error reading predefined tags Configuration, reverting to default.",
|
||||||
"Error reading shared tags Configuration", NotificationType.Error);
|
"Error reading predefined tags Configuration", NotificationType.Error);
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
static void HandleDeserializationError(object? sender, ErrorEventArgs errorArgs)
|
|
||||||
{
|
|
||||||
Penumbra.Log.Error(
|
|
||||||
$"Error parsing shared tags Configuration at {errorArgs.ErrorContext.Path}, using default or migrating:\n{errorArgs.ErrorContext.Error}");
|
|
||||||
errorArgs.ErrorContext.Handled = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeSharedTag(int tagIdx, string tag)
|
public void ChangeSharedTag(int tagIdx, string tag)
|
||||||
{
|
{
|
||||||
if (tagIdx < 0 || tagIdx > PredefinedTags.Count)
|
if (tagIdx < 0 || tagIdx > _predefinedTags.Count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// In the case of editing a tag, remove what's there prior to doing an insert.
|
if (tagIdx != _predefinedTags.Count)
|
||||||
if (tagIdx != PredefinedTags.Count)
|
|
||||||
_predefinedTags.RemoveAt(tagIdx);
|
_predefinedTags.RemoveAt(tagIdx);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tag))
|
if (!string.IsNullOrEmpty(tag))
|
||||||
{
|
_predefinedTags.TryAdd(tag, default);
|
||||||
// Taking advantage of the fact that BinarySearch returns the complement of the correct sorted position for the tag.
|
|
||||||
var existingIdx = _predefinedTags.BinarySearch(tag);
|
|
||||||
if (existingIdx < 0)
|
|
||||||
_predefinedTags.Insert(~existingIdx, tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
@ -147,7 +137,7 @@ public sealed class PredefinedTagManager : ISavable
|
||||||
_enabledColor = ColorId.PredefinedTagAdd.Value();
|
_enabledColor = ColorId.PredefinedTagAdd.Value();
|
||||||
_disabledColor = ColorId.PredefinedTagRemove.Value();
|
_disabledColor = ColorId.PredefinedTagRemove.Value();
|
||||||
var (edited, others) = editLocal ? (localTags, modTags) : (modTags, localTags);
|
var (edited, others) = editLocal ? (localTags, modTags) : (modTags, localTags);
|
||||||
foreach (var (tag, idx) in PredefinedTags.WithIndex())
|
foreach (var (tag, idx) in _predefinedTags.Keys.WithIndex())
|
||||||
{
|
{
|
||||||
var tagIdx = edited.IndexOf(tag);
|
var tagIdx = edited.IndexOf(tag);
|
||||||
var inOther = tagIdx < 0 && others.IndexOf(tag) >= 0;
|
var inOther = tagIdx < 0 && others.IndexOf(tag) >= 0;
|
||||||
|
|
@ -189,4 +179,16 @@ public sealed class PredefinedTagManager : ISavable
|
||||||
|
|
||||||
private static float CalcTextButtonWidth(string text)
|
private static float CalcTextButtonWidth(string text)
|
||||||
=> ImGui.CalcTextSize(text).X + 2 * ImGui.GetStyle().FramePadding.X;
|
=> ImGui.CalcTextSize(text).X + 2 * ImGui.GetStyle().FramePadding.X;
|
||||||
|
|
||||||
|
public IEnumerator<string> GetEnumerator()
|
||||||
|
=> _predefinedTags.Keys.GetEnumerator();
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
=> GetEnumerator();
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
=> _predefinedTags.Count;
|
||||||
|
|
||||||
|
public string this[int index]
|
||||||
|
=> _predefinedTags.Keys[index];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -924,7 +924,7 @@ public class SettingsTab : ITab
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var tagIdx = _sharedTags.Draw("Predefined Tags: ",
|
var tagIdx = _sharedTags.Draw("Predefined Tags: ",
|
||||||
"Predefined tags that can be added or removed from mods with a single click.", _predefinedTagManager.PredefinedTags,
|
"Predefined tags that can be added or removed from mods with a single click.", _predefinedTagManager,
|
||||||
out var editedTag);
|
out var editedTag);
|
||||||
|
|
||||||
if (tagIdx >= 0)
|
if (tagIdx >= 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue