From 8f9c01d3226ec30197d3de8600fc03b9ebd8520f Mon Sep 17 00:00:00 2001 From: JonKazama-Hellion Date: Tue, 5 May 2026 14:13:19 +0200 Subject: [PATCH] feat(themes): mini-mockup preview in theme cards --- HellionChat/Ui/SettingsTabs/ThemeMockup.cs | 70 ++++++++++++++++++++++ HellionChat/Ui/SettingsTabs/Themes.cs | 25 +++----- 2 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 HellionChat/Ui/SettingsTabs/ThemeMockup.cs diff --git a/HellionChat/Ui/SettingsTabs/ThemeMockup.cs b/HellionChat/Ui/SettingsTabs/ThemeMockup.cs new file mode 100644 index 0000000..3fcb382 --- /dev/null +++ b/HellionChat/Ui/SettingsTabs/ThemeMockup.cs @@ -0,0 +1,70 @@ +using System.Numerics; +using Dalamud.Bindings.ImGui; +using HellionChat.Themes; +using HellionChat.Util; + +namespace HellionChat.Ui.SettingsTabs; + +internal static class ThemeMockup +{ + // Zeichnet ein Mini-Chat-Window-Mockup mit den Theme-Werten direkt + // ins WindowDrawList. Keine Texture, keine Allocation pro Frame — + // alles via DrawList.AddRectFilled / AddText. + public static void Draw(Vector2 origin, Vector2 size, Theme theme) + { + var draw = ImGui.GetWindowDrawList(); + var c = theme.Colors; + + // Window-Bg + draw.AddRectFilled(origin, origin + size, ColourUtil.RgbaToAbgr(c.WindowBg | 0xFFu), theme.Layout.WindowRounding); + + // Title-Bar + var titleHeight = 14f; + draw.AddRectFilled( + origin, + new Vector2(origin.X + size.X, origin.Y + titleHeight), + ColourUtil.RgbaToAbgr(c.Identity), theme.Layout.WindowRounding); + + // Tab-Bar — 3 Mini-Tabs + var tabY = origin.Y + titleHeight + 4f; + var tabHeight = 12f; + for (var i = 0; i < 3; i++) + { + var tabX = origin.X + 6f + i * 28f; + var color = i == 0 ? c.FrameBg : c.ChildBg; + draw.AddRectFilled( + new Vector2(tabX, tabY), + new Vector2(tabX + 26f, tabY + tabHeight), + ColourUtil.RgbaToAbgr(color), theme.Layout.TabRounding); + + if (i == 0) // Active-Pill + { + draw.AddRectFilled( + new Vector2(tabX, tabY + tabHeight - 2f), + new Vector2(tabX + 26f, tabY + tabHeight), + ColourUtil.RgbaToAbgr(c.Primary)); + } + } + + // Card-Row mit Mock-Sender + Text + var rowY = tabY + tabHeight + 6f; + var rowHeight = 18f; + draw.AddRectFilled( + new Vector2(origin.X + 6f, rowY), + new Vector2(origin.X + size.X - 6f, rowY + rowHeight), + ColourUtil.RgbaToAbgr(c.Surface), 2f); + + // Akzent-Button rechts unten + var btnW = 28f; + var btnH = 10f; + var btnX = origin.X + size.X - btnW - 6f; + var btnY = origin.Y + size.Y - btnH - 6f; + draw.AddRectFilled( + new Vector2(btnX, btnY), + new Vector2(btnX + btnW, btnY + btnH), + ColourUtil.RgbaToAbgr(c.Accent), theme.Layout.FrameRounding); + + // Border um das gesamte Mockup + draw.AddRect(origin, origin + size, ColourUtil.RgbaToAbgr(c.Border), theme.Layout.WindowRounding); + } +} diff --git a/HellionChat/Ui/SettingsTabs/Themes.cs b/HellionChat/Ui/SettingsTabs/Themes.cs index f04a5de..f501b6b 100644 --- a/HellionChat/Ui/SettingsTabs/Themes.cs +++ b/HellionChat/Ui/SettingsTabs/Themes.cs @@ -82,7 +82,7 @@ internal sealed class Themes : ISettingsTab var avail = ImGui.GetContentRegionAvail(); var columns = avail.X >= 700f ? 3 : 2; var cardWidth = (avail.X - (columns - 1) * 8f) / columns; - var cardHeight = 110f; + var cardHeight = 140f; // war 110f — Mockup braucht mehr Platz var i = 0; foreach (var theme in themes) { @@ -117,30 +117,23 @@ internal sealed class Themes : ISettingsTab draw.AddRect(cursorBefore, cursorBefore + new Vector2(w, h), border, 4f, ImDrawFlags.None, 1f); } - // Akzent-Swatch links oben - var swatchPos = cursorBefore + new Vector2(12f, 12f); - var swatchSize = new Vector2(20f, 20f); - draw.AddRectFilled(swatchPos, swatchPos + swatchSize, ColourUtil.RgbaToAbgr(theme.Colors.Primary), 3f); + // Mini-Mockup statt Akzent-Swatch — visualisiert das Theme im Mini-Chat-Window + var mockupOrigin = cursorBefore + new Vector2(12f, 12f); + var mockupSize = new Vector2(w - 24f, 60f); + ThemeMockup.Draw(mockupOrigin, mockupSize, theme); - // Name - ImGui.SetCursorScreenPos(cursorBefore + new Vector2(40f, 12f)); + // Name unter dem Mockup + ImGui.SetCursorScreenPos(cursorBefore + new Vector2(12f, 78f)); var textColor = ColourUtil.RgbaToAbgr(theme.Colors.TextPrimary); using (ImRaii.PushColor(ImGuiCol.Text, textColor)) ImGui.TextUnformatted(theme.Name); - // Author - ImGui.SetCursorScreenPos(cursorBefore + new Vector2(40f, 32f)); + // Author dahinter dezent + ImGui.SetCursorScreenPos(cursorBefore + new Vector2(12f, 96f)); var mutedColor = ColourUtil.RgbaToAbgr(theme.Colors.TextMuted); using (ImRaii.PushColor(ImGuiCol.Text, mutedColor)) ImGui.TextUnformatted(theme.Author); - // Description (wrapped, falls zu lang) - ImGui.SetCursorScreenPos(cursorBefore + new Vector2(12f, 60f)); - ImGui.PushTextWrapPos(cursorBefore.X + w - 12f); - using (ImRaii.PushColor(ImGuiCol.Text, mutedColor)) - ImGui.TextUnformatted(theme.Description); - ImGui.PopTextWrapPos(); - // Cursor unter die Card setzen ImGui.SetCursorScreenPos(cursorBefore + new Vector2(0f, h + 8f));