feat(style-engine): add PushStack as ImRaii bridge
DI-singleton that pairs Token lookups with ImRaii's tracked push/pop machinery. Begin() returns a disposable PushScope with fluent Color, Style (float/Vector2) and Font methods; reverse-order dispose runs through the collected IDisposables. Counter-symmetry and exception-safety come from ImRaii, this layer just handles the token → ImGuiCol resolution and the RGBA → ABGR conversion at the ImGui boundary.
This commit is contained in:
@@ -93,6 +93,9 @@ internal static class PluginHostFactory
|
|||||||
));
|
));
|
||||||
|
|
||||||
services.AddSingleton(_ => new Ui.StyleEngine.TokenResolver());
|
services.AddSingleton(_ => new Ui.StyleEngine.TokenResolver());
|
||||||
|
services.AddSingleton(sp => new Ui.StyleEngine.PushStack(
|
||||||
|
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
|
||||||
|
));
|
||||||
|
|
||||||
services.AddSingleton(sp => new GameFunctions.GameFunctions(
|
services.AddSingleton(sp => new GameFunctions.GameFunctions(
|
||||||
sp.GetRequiredService<Plugin>(),
|
sp.GetRequiredService<Plugin>(),
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
using HellionChat.Themes;
|
||||||
|
using HellionChat.Util;
|
||||||
|
|
||||||
|
namespace HellionChat.Ui.StyleEngine;
|
||||||
|
|
||||||
|
// Token-aware bridge over Dalamud's ImRaii. Couples semantic Token lookups
|
||||||
|
// to the already-tracked push/pop machinery so callers express style intent
|
||||||
|
// instead of raw ImGuiCol slots. Counter-symmetry and exception-safety come
|
||||||
|
// from ImRaii, not from this class.
|
||||||
|
internal sealed class PushStack
|
||||||
|
{
|
||||||
|
private readonly TokenResolver _resolver;
|
||||||
|
|
||||||
|
public PushStack(TokenResolver resolver)
|
||||||
|
{
|
||||||
|
_resolver = resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PushScope Begin() => new(_resolver);
|
||||||
|
|
||||||
|
// Disposable scope handed to the using-block. Each Push.* call is a thin
|
||||||
|
// delegate to ImRaii / IFontHandle.Push with the token resolve in front;
|
||||||
|
// disposes in reverse order via the captured IDisposables.
|
||||||
|
internal sealed class PushScope : IDisposable
|
||||||
|
{
|
||||||
|
private readonly List<IDisposable> _items = new(32);
|
||||||
|
private readonly TokenResolver _resolver;
|
||||||
|
|
||||||
|
internal PushScope(TokenResolver resolver)
|
||||||
|
{
|
||||||
|
_resolver = resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PushScope Color(Token token, Theme theme)
|
||||||
|
{
|
||||||
|
var slot = TokenMap.ToImGuiCol(token);
|
||||||
|
var rgba = _resolver.Resolve(token, theme.Colors);
|
||||||
|
_items.Add(ImRaii.PushColor(slot, ColourUtil.RgbaToAbgr(rgba)));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PushScope Style(ImGuiStyleVar var, float value)
|
||||||
|
{
|
||||||
|
_items.Add(ImRaii.PushStyle(var, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PushScope Style(ImGuiStyleVar var, Vector2 value)
|
||||||
|
{
|
||||||
|
_items.Add(ImRaii.PushStyle(var, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PushScope Font(IFontHandle font)
|
||||||
|
{
|
||||||
|
_items.Add(font.Push());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
for (var i = _items.Count - 1; i >= 0; i--)
|
||||||
|
_items[i].Dispose();
|
||||||
|
_items.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user