3da550c2fc
Settings → Erscheinungsbild → Schriftarten: bei aktiver 'Mitgelieferte Hellion-Schrift (Exo 2) verwenden' war der Schriftgrößen-Slider ausgegraut und FontSizeV2 wurde im FontManager auch nicht angewendet — 4K-User konnten den Plugin-Font nicht hochskalieren. Exo 2 ist Variable-Font, FontSize ist also problemlos adjustierbar. Zwei-teiliger Fix: - Appearance.cs: UseHellionFont rendert jetzt nur FontSizeCombo + SymbolsFontSizeCombo, kein Disabled-Wrap mehr. Der Bestand- Custom-Font-Stack mit FontsEnabled-Toggle und Font-Choosern bleibt exclusive zur Hellion-Schrift, läuft im else-Pfad. - FontManager.cs RegularFont-Build: SizePt-Source verzweigt jetzt auf UseHellionFont — Hellion-Pfad nutzt FontSizeV2, Bestand-Pfad nutzt weiter GlobalFontV2.SizePt aus dem Custom-Font-Spec. Reported by Flo 2026-05-06: '4k monitor ... der standart zu klein'.
358 lines
14 KiB
C#
358 lines
14 KiB
C#
using HellionChat.Code;
|
|
using HellionChat.Resources;
|
|
using HellionChat.Util;
|
|
using Dalamud;
|
|
using Dalamud.Interface;
|
|
using Dalamud.Interface.FontIdentifier;
|
|
using Dalamud.Interface.Style;
|
|
using Dalamud.Interface.Utility;
|
|
using Dalamud.Interface.Utility.Raii;
|
|
using Dalamud.Bindings.ImGui;
|
|
|
|
namespace HellionChat.Ui.SettingsTabs;
|
|
|
|
internal sealed class Appearance : ISettingsTab
|
|
{
|
|
private Plugin Plugin { get; }
|
|
private Configuration Mutable { get; }
|
|
|
|
public string Name => HellionStrings.Settings_Tab_Appearance + "###tabs-appearance";
|
|
|
|
internal Appearance(Plugin plugin, Configuration mutable)
|
|
{
|
|
Plugin = plugin;
|
|
Mutable = mutable;
|
|
}
|
|
|
|
public void Draw(bool changed)
|
|
{
|
|
DrawThemeSection();
|
|
ImGui.Spacing();
|
|
DrawFontsSection();
|
|
ImGui.Spacing();
|
|
DrawColoursSection();
|
|
ImGui.Spacing();
|
|
DrawTimestampsSection();
|
|
}
|
|
|
|
private void DrawThemeSection()
|
|
{
|
|
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Appearance_Theme_Heading);
|
|
if (!tree.Success)
|
|
{
|
|
return;
|
|
}
|
|
|
|
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
|
|
{
|
|
// v1.2.0 — Legacy HellionThemeEnabled/HellionThemeWindowOpacity-Bindings
|
|
// entfernt. Theme-Auswahl + globale Window-Opacity leben jetzt in
|
|
// Settings → Themes (eingeführt mit v1.1.0). Hier verbleibt nur der
|
|
// klassische OverrideStyle-Toggle plus der Bestand-WindowAlpha-Slider
|
|
// für das Chat-Log-Fenster.
|
|
ImGui.Checkbox(Language.Options_OverrideStyle_Name, ref Mutable.OverrideStyle);
|
|
ImGuiUtil.HelpMarker(Language.Options_OverrideStyle_Name_Desc);
|
|
|
|
if (Mutable.OverrideStyle)
|
|
{
|
|
DrawStyleCombo();
|
|
}
|
|
|
|
ImGuiUtil.DragFloatVertical(Language.Options_WindowOpacity_Name, ref Mutable.WindowAlpha, .25f, 0f, 100f, $"{Mutable.WindowAlpha:N2}%%", ImGuiSliderFlags.AlwaysClamp);
|
|
}
|
|
}
|
|
|
|
private void DrawStyleCombo()
|
|
{
|
|
var styles = StyleModel.GetConfiguredStyles();
|
|
if (styles == null)
|
|
{
|
|
ImGui.TextUnformatted(Language.Options_OverrideStyle_NotAvailable);
|
|
return;
|
|
}
|
|
|
|
var currentStyle = Mutable.ChosenStyle ?? Language.Options_OverrideStyle_NotSelected;
|
|
using var combo = ImRaii.Combo(Language.Options_OverrideStyleDropdown_Name, currentStyle);
|
|
if (!combo)
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach (var style in styles)
|
|
{
|
|
if (ImGui.Selectable(style.Name, Mutable.ChosenStyle == style.Name))
|
|
{
|
|
Mutable.ChosenStyle = style.Name;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawFontsSection()
|
|
{
|
|
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Appearance_Fonts_Heading);
|
|
if (!tree.Success)
|
|
{
|
|
return;
|
|
}
|
|
|
|
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
|
|
{
|
|
if (ImGui.Checkbox(HellionStrings.Theme_UseHellionFont_Name, ref Mutable.UseHellionFont))
|
|
{
|
|
// Mutex with the Bestand custom-font stack. Leaving FontsEnabled
|
|
// checked alongside UseHellionFont made both checkboxes look
|
|
// active even though the lower stack was greyed out, which
|
|
// confused the user during the v0.5.0 walkthrough.
|
|
if (Mutable.UseHellionFont)
|
|
Mutable.FontsEnabled = false;
|
|
}
|
|
ImGuiUtil.HelpMarker(HellionStrings.Theme_UseHellionFont_Description);
|
|
ImGui.Spacing();
|
|
|
|
// v1.2.0 — Schriftgröße muss auch bei aktiver Hellion-Schrift
|
|
// editierbar sein (Exo 2 ist Variable-Font, FontSizeV2 wird in
|
|
// FontManager als SizePt angewendet). Disabled-Wrap nur noch
|
|
// um den Bestand-Custom-Font-Stack (FontsEnabled-Toggle und
|
|
// die Font-Chooser) — der ist weiter exclusive zu HellionFont.
|
|
if (Mutable.UseHellionFont)
|
|
{
|
|
ImGuiUtil.FontSizeCombo(Language.Options_FontSize_Name, ref Mutable.FontSizeV2);
|
|
ImGui.Spacing();
|
|
|
|
ImGuiUtil.FontSizeCombo(Language.Options_SymbolsFontSize_Name, ref Mutable.SymbolsFontSizeV2);
|
|
ImGuiUtil.HelpMarker(Language.Options_SymbolsFontSize_Description);
|
|
|
|
ImGui.Spacing();
|
|
return;
|
|
}
|
|
|
|
ImGui.Checkbox(Language.Options_FontsEnabled, ref Mutable.FontsEnabled);
|
|
ImGui.Spacing();
|
|
|
|
var unused = false;
|
|
if (!Mutable.FontsEnabled)
|
|
{
|
|
ImGuiUtil.FontSizeCombo(Language.Options_FontSize_Name, ref Mutable.FontSizeV2);
|
|
}
|
|
else
|
|
{
|
|
var globalChooser = ImGuiUtil.FontChooser(Language.Options_Font_Name, Mutable.GlobalFontV2, false, ref unused);
|
|
globalChooser?.ResultTask.ContinueWith(r =>
|
|
{
|
|
if (r.IsCompletedSuccessfully)
|
|
{
|
|
Plugin.Framework.Run(() => Mutable.GlobalFontV2 = r.Result);
|
|
}
|
|
});
|
|
ImGui.SameLine();
|
|
if (ImGui.Button("Reset##global"))
|
|
{
|
|
Mutable.GlobalFontV2 = new SingleFontSpec { FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkRegular), SizePt = 12.75f };
|
|
}
|
|
|
|
ImGuiUtil.HelpMarker(string.Format(Language.Options_Font_Description, Plugin.PluginName));
|
|
ImGuiUtil.WarningText(Language.Options_Font_Warning);
|
|
ImGui.Spacing();
|
|
|
|
// LocaleNames being null means it is likely a game font which all support JP symbols.
|
|
var japaneseChooser = ImGuiUtil.FontChooser(Language.Options_JapaneseFont_Name, Mutable.JapaneseFontV2, false, ref unused, id => !id.LocaleNames?.ContainsKey("ja-jp") ?? false, "いろはにほへと ちりぬるを");
|
|
japaneseChooser?.ResultTask.ContinueWith(r =>
|
|
{
|
|
if (r.IsCompletedSuccessfully)
|
|
{
|
|
Plugin.Framework.Run(() => Mutable.JapaneseFontV2 = r.Result);
|
|
}
|
|
});
|
|
ImGui.SameLine();
|
|
if (ImGui.Button("Reset##japanese"))
|
|
{
|
|
Mutable.JapaneseFontV2 = new SingleFontSpec { FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkMedium), SizePt = 12.75f };
|
|
}
|
|
|
|
ImGuiUtil.HelpMarker(string.Format(Language.Options_JapaneseFont_Description, Plugin.PluginName));
|
|
ImGui.Spacing();
|
|
|
|
var italicChooser = ImGuiUtil.FontChooser(Language.Options_ItalicFont_Name, Mutable.ItalicFontV2, true, ref Mutable.ItalicEnabled);
|
|
italicChooser?.ResultTask.ContinueWith(r =>
|
|
{
|
|
if (r.IsCompletedSuccessfully)
|
|
{
|
|
Plugin.Framework.Run(() => Mutable.ItalicFontV2 = r.Result);
|
|
}
|
|
});
|
|
ImGui.SameLine();
|
|
if (ImGui.Button("Reset##italic"))
|
|
{
|
|
Mutable.ItalicEnabled = false;
|
|
Mutable.ItalicFontV2 = new SingleFontSpec { FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkRegular), SizePt = 12.75f };
|
|
}
|
|
|
|
ImGuiUtil.HelpMarker(string.Format(Language.Options_Italic_Description, Plugin.PluginName));
|
|
ImGui.Spacing();
|
|
|
|
if (ImGui.CollapsingHeader(Language.Options_ExtraGlyphs_Name))
|
|
{
|
|
ImGuiUtil.HelpMarker(string.Format(Language.Options_ExtraGlyphs_Description, Plugin.PluginName));
|
|
|
|
var range = (int)Mutable.ExtraGlyphRanges;
|
|
foreach (var extra in Enum.GetValues<ExtraGlyphRanges>())
|
|
{
|
|
ImGui.CheckboxFlags(extra.Name(), ref range, (int)extra);
|
|
}
|
|
|
|
Mutable.ExtraGlyphRanges = (ExtraGlyphRanges)range;
|
|
}
|
|
|
|
ImGui.Spacing();
|
|
}
|
|
|
|
ImGuiUtil.FontSizeCombo(Language.Options_SymbolsFontSize_Name, ref Mutable.SymbolsFontSizeV2);
|
|
ImGuiUtil.HelpMarker(Language.Options_SymbolsFontSize_Description);
|
|
|
|
ImGui.Spacing();
|
|
}
|
|
}
|
|
|
|
private void DrawColoursSection()
|
|
{
|
|
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Appearance_Colours_Heading);
|
|
if (!tree.Success)
|
|
{
|
|
return;
|
|
}
|
|
|
|
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
|
|
{
|
|
DrawColourPresetButtons();
|
|
ImGui.TextDisabled(HellionStrings.Settings_Appearance_Colours_PresetsHint);
|
|
ImGui.Spacing();
|
|
ImGui.Separator();
|
|
ImGui.Spacing();
|
|
|
|
ImGui.Checkbox(Language.Options_ColorSelectedInputChannelButton_Name, ref Mutable.ColorSelectedInputChannelButton);
|
|
ImGuiUtil.HelpMarker(Language.Options_ColorSelectedInputChannelButton_Description);
|
|
ImGui.Spacing();
|
|
|
|
foreach (var (_, types) in ChatTypeExt.SortOrder)
|
|
{
|
|
foreach (var type in types)
|
|
{
|
|
if (ImGuiUtil.IconButton(FontAwesomeIcon.UndoAlt, $"{type}", Language.Options_ChatColours_Reset))
|
|
{
|
|
Mutable.ChatColours.Remove(type);
|
|
}
|
|
|
|
ImGui.SameLine();
|
|
|
|
if (ImGuiUtil.IconButton(FontAwesomeIcon.LongArrowAltDown, $"{type}", Language.Options_ChatColours_Import))
|
|
{
|
|
var gameColour = Plugin.Functions.Chat.GetChannelColor(type);
|
|
Mutable.ChatColours[type] = gameColour ?? type.DefaultColor() ?? 0;
|
|
}
|
|
|
|
ImGui.SameLine();
|
|
|
|
var vec = Mutable.ChatColours.TryGetValue(type, out var colour)
|
|
? ColourUtil.RgbaToVector3(colour)
|
|
: ColourUtil.RgbaToVector3(type.DefaultColor() ?? 0);
|
|
if (ImGui.ColorEdit3(type.Name(), ref vec, ImGuiColorEditFlags.NoInputs))
|
|
{
|
|
Mutable.ChatColours[type] = ColourUtil.Vector3ToRgba(vec);
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui.Spacing();
|
|
}
|
|
}
|
|
|
|
// Hellion Chat — v0.6.0 preset-buttons row above the per-channel colour
|
|
// editors. Apply is immediate and overwrites every channel covered by
|
|
// the preset; channels not in the preset keep their current colour.
|
|
private void DrawColourPresetButtons()
|
|
{
|
|
var first = true;
|
|
foreach (var (_, preset) in ChatColourPresets.All)
|
|
{
|
|
if (!first)
|
|
{
|
|
ImGui.SameLine();
|
|
}
|
|
first = false;
|
|
|
|
if (preset.IsBrandPreset)
|
|
{
|
|
// Hellion-Brand visuell hervorheben — blau-violetter Frame-Akzent
|
|
var border = ColourUtil.RgbaToVector3(ColourUtil.ComponentsToRgba(255, 128, 200));
|
|
var btn = ColourUtil.RgbaToVector3(ColourUtil.ComponentsToRgba(74, 42, 106));
|
|
ImGui.PushStyleColor(ImGuiCol.Border, new System.Numerics.Vector4(border.X, border.Y, border.Z, 1f));
|
|
ImGui.PushStyleColor(ImGuiCol.Button, new System.Numerics.Vector4(btn.X, btn.Y, btn.Z, 1f));
|
|
ImGui.PushStyleVar(ImGuiStyleVar.FrameBorderSize, 1.5f);
|
|
}
|
|
|
|
if (ImGui.Button(GetPresetLabel(preset)))
|
|
{
|
|
ApplyPreset(preset);
|
|
}
|
|
|
|
if (preset.IsBrandPreset)
|
|
{
|
|
ImGui.PopStyleVar();
|
|
ImGui.PopStyleColor(2);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Localized label for a preset; falls back to DisplayName if the i18n
|
|
// key is missing (defensive — the resource manager returns the key
|
|
// string itself when a lookup fails).
|
|
private static string GetPresetLabel(ChatColourPreset preset)
|
|
{
|
|
var localized = HellionStrings.ResourceManager.GetString(preset.LocalizationKey, HellionStrings.Culture);
|
|
return string.IsNullOrEmpty(localized) ? preset.DisplayName : localized;
|
|
}
|
|
|
|
private void ApplyPreset(ChatColourPreset preset)
|
|
{
|
|
foreach (var (channel, colour) in preset.Colours)
|
|
{
|
|
Mutable.ChatColours[channel] = colour;
|
|
}
|
|
Plugin.SaveConfig();
|
|
GlobalParametersCache.Refresh();
|
|
Plugin.Log.Debug($"Applied chat colour preset: {preset.DisplayName}");
|
|
}
|
|
|
|
private void DrawTimestampsSection()
|
|
{
|
|
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Appearance_Timestamps_Heading);
|
|
if (!tree.Success)
|
|
{
|
|
return;
|
|
}
|
|
|
|
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
|
|
{
|
|
ImGui.Checkbox(Language.Options_PrettierTimestamps_Name, ref Mutable.PrettierTimestamps);
|
|
ImGuiUtil.HelpMarker(Language.Options_PrettierTimestamps_Description);
|
|
|
|
if (Mutable.PrettierTimestamps)
|
|
{
|
|
ImGui.Checkbox(Language.Options_MoreCompactPretty_Name, ref Mutable.MoreCompactPretty);
|
|
ImGuiUtil.HelpMarker(Language.Options_MoreCompactPretty_Description);
|
|
|
|
// v1.2.0 — Card-Rows als Default. Compact-Density schaltet auf den
|
|
// klassischen Single-Line-Mode `[HH:mm] Sender: Text` zurück.
|
|
ImGui.Checkbox(HellionStrings.Appearance_UseCompactDensity_Name, ref Mutable.UseCompactDensity);
|
|
ImGuiUtil.HelpMarker(HellionStrings.Appearance_UseCompactDensity_Description);
|
|
|
|
ImGui.Checkbox(Language.Options_HideSameTimestamps_Name, ref Mutable.HideSameTimestamps);
|
|
ImGuiUtil.HelpMarker(Language.Options_HideSameTimestamps_Description);
|
|
}
|
|
|
|
ImGui.Checkbox(Language.Options_Use24HourClock_Name, ref Mutable.Use24HourClock);
|
|
ImGuiUtil.HelpMarker(Language.Options_Use24HourClock_Description);
|
|
}
|
|
}
|
|
}
|