Files
HSUI/Interface/GeneralElements/FontsConfig.cs

402 lines
13 KiB
C#

using Dalamud.Interface;
using Dalamud.Interface.ImGuiFileDialog;
using HSUI.Config;
using HSUI.Config.Attributes;
using HSUI.Helpers;
using Dalamud.Bindings.ImGui;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using Dalamud.Interface.GameFonts;
using Dalamud.Logging;
using HSUI.Enums;
using HSUI.Interface.Bars;
namespace HSUI.Interface.GeneralElements
{
public struct FontData
{
public string Name;
public int Size;
public FontData(string name, int size)
{
Name = name;
Size = size;
}
}
[Disableable(false)]
[Section("Customization")]
[SubSection("Fonts", 0)]
public class FontsConfig : PluginConfigObject
{
public new static FontsConfig DefaultConfig() { return new FontsConfig(); }
public string FontsPath = "C:\\";
[JsonIgnore] public string ValidatedFontsPath => ValidatePath(FontsPath);
public SortedList<string, FontData> Fonts = new SortedList<string, FontData>();
public bool SupportChineseCharacters = false;
public bool SupportKoreanCharacters = false;
public bool SupportCyrillicCharacters = false;
[JsonIgnore] public readonly Dictionary<string, string> GameFontMap = new Dictionary<string, string>()
{
{"Axis", "axis-ffxiv"},
{"Jupiter", "jupiter-ffxiv"},
{"JupiterNumeric", "jupiter-numeric-ffxiv"},
{"MiedingerMid", "meidinger-ffxiv"},
{"Meidinger", "meidinger-numberic-ffxiv"},
{"TrumpGothic", "trumpgothic-ffxiv"},
};
[JsonIgnore] public static readonly List<string> DefaultFontsKeys = new List<string>() { "Expressway_18", "Expressway_14", "Expressway_12" };
[JsonIgnore] public static string DefaultBigFontKey => DefaultFontsKeys[0];
[JsonIgnore] public static string DefaultMediumFontKey => DefaultFontsKeys[1];
[JsonIgnore] public static string DefaultSmallFontKey => DefaultFontsKeys[2];
[JsonIgnore] private int _inputFont = 0;
[JsonIgnore] private int _inputSize = 23;
[JsonIgnore] private string[] _fonts = null!;
[JsonIgnore] private string[] _sizes = null!;
[JsonIgnore] private int _removingIndex = -1;
[JsonIgnore] private int _applyingIndex = -1!;
[JsonIgnore] private FileDialogManager _fileDialogManager = new FileDialogManager();
public FontsConfig()
{
ReloadFonts();
// default fonts
foreach (string key in DefaultFontsKeys)
{
if (!Fonts.ContainsKey(key))
{
string[] str = key.Split("_", StringSplitOptions.RemoveEmptyEntries);
var defaultFont = new FontData(str[0], int.Parse(str[1]));
Fonts.Add(key, defaultFont);
}
}
// sizes
_sizes = new string[100];
for (int i = 0; i < _sizes.Length; i++)
{
_sizes[i] = (i + 1).ToString();
}
}
private bool IsDefaultFont(string key)
{
return DefaultFontsKeys.Contains(key);
}
private string ValidatePath(string path)
{
if (path.EndsWith("\\") || path.EndsWith("/"))
{
return path;
}
return path + "\\";
}
private string[] FontsFromPath(string path)
{
string[] fonts;
try
{
fonts = Directory.GetFiles(path, "*.ttf");
}
catch
{
fonts = new string[0];
}
for (int i = 0; i < fonts.Length; i++)
{
fonts[i] = fonts[i]
.Replace(path, "")
.Replace(".ttf", "")
.Replace(".TTF", "");
}
return fonts;
}
private string[] FontsFromGame()
{
string[] gameFontArray = Enum.GetNames(typeof(GameFontFamily)).Skip(1).ToArray();
string[] fonts = new string[gameFontArray.Length];
for (int i = 0; i < gameFontArray.Length; i++)
{
fonts[i] = GameFontMap[gameFontArray[i]];
}
return fonts;
}
private void ReloadFonts()
{
string defaultFontsPath = ValidatePath(FontsManager.Instance.DefaultFontsPath);
string[] defaultFonts = FontsFromPath(defaultFontsPath);
string[] gameFonts = FontsFromGame();
string[] userFonts = FontsFromPath(ValidatedFontsPath);
_fonts = new string[defaultFonts.Length + gameFonts.Length + userFonts.Length];
defaultFonts.CopyTo(_fonts, 0);
gameFonts.CopyTo(_fonts, defaultFonts.Length);
userFonts.CopyTo(_fonts, defaultFonts.Length + gameFonts.Length);
}
private bool AddNewEntry(int font, int size)
{
if (font < 0 || font > _fonts.Length)
{
return false;
}
if (size <= 0 || size > _sizes.Length)
{
return false;
}
string fontName = _fonts[font];
string key = fontName + "_" + size.ToString();
if (Fonts.ContainsKey(key))
{
return false;
}
FontData fontData = new FontData(fontName, size);
Fonts.Add(key, fontData);
FontsManager.Instance.BuildFonts();
return true;
}
private void SelectFolder()
{
Action<bool, string> callback = (finished, path) =>
{
if (finished && path.Length > 0)
{
FontsPath = path;
ReloadFonts();
}
};
_fileDialogManager.OpenFolderDialog("Select Fonts Folder", callback);
}
[ManualDraw]
public bool Draw(ref bool changed)
{
ImGuiTableFlags flags =
ImGuiTableFlags.RowBg |
ImGuiTableFlags.Borders |
ImGuiTableFlags.BordersOuter |
ImGuiTableFlags.BordersInner |
ImGuiTableFlags.ScrollY |
ImGuiTableFlags.SizingFixedSame;
if (ImGui.BeginChild("Fonts", new Vector2(800, 500), false, ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse))
{
if (_fonts.Length == 0)
{
ImGuiHelper.Tab();
ImGui.Text("Default font not found in \"%appdata%/Roaming/XIVLauncher/InstalledPlugins/HSUI/Media/Fonts/Expressway.ttf\"");
return false;
}
ImGuiHelper.NewLineAndTab();
if (ImGui.InputText("Path", ref FontsPath, 200, ImGuiInputTextFlags.EnterReturnsTrue))
{
changed = true;
ReloadFonts();
}
ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Folder.ToIconString(), new Vector2(0, 0)))
{
SelectFolder();
}
ImGui.PopFont();
ImGuiHelper.Tab();
ImGui.Combo("Font ##font", ref _inputFont, _fonts, 10);
ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button("\uf2f9", new Vector2(0, 0)))
{
ReloadFonts();
}
ImGui.PopFont();
ImGuiHelper.Tab();
ImGui.Combo("Size ##size", ref _inputSize, _sizes, 10);
ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString(), new Vector2(0, 0)))
{
changed |= AddNewEntry(_inputFont, _inputSize + 1);
}
ImGui.PopFont();
ImGuiHelper.NewLineAndTab();
if (ImGui.BeginTable("table", 3, flags, new Vector2(326, 300)))
{
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthStretch, 0, 0);
ImGui.TableSetupColumn("Size", ImGuiTableColumnFlags.WidthFixed, 0, 1);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.WidthFixed, 0, 2);
ImGui.TableSetupScrollFreeze(0, 1);
ImGui.TableHeadersRow();
for (int i = 0; i < Fonts.Count; i++)
{
var key = Fonts.Keys[i];
var fontData = Fonts.Values[i];
ImGui.PushID(i.ToString());
ImGui.TableNextRow(ImGuiTableRowFlags.None);
// icon
if (ImGui.TableSetColumnIndex(0))
{
ImGui.Text(fontData.Name);
}
// id
if (ImGui.TableSetColumnIndex(1))
{
ImGui.Text(fontData.Size.ToString());
}
// remove
if (ImGui.TableSetColumnIndex(2))
{
ImGui.PushFont(UiBuilder.IconFont);
ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero);
ImGui.PushStyleColor(ImGuiCol.ButtonActive, Vector4.Zero);
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, Vector4.Zero);
if (ImGui.Button(FontAwesomeIcon.ArrowAltCircleUp.ToIconString()))
{
_applyingIndex = i;
}
if (!IsDefaultFont(key))
{
ImGui.SameLine();
if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString()))
{
_removingIndex = i;
}
}
ImGui.PopFont();
ImGui.PopStyleColor(3);
}
ImGui.PopID();
}
ImGui.EndTable();
}
ImGuiHelper.NewLineAndTab();
if (ImGui.Checkbox("Support Chinese", ref SupportChineseCharacters))
{
changed = true;
FontsManager.Instance.BuildFonts();
}
ImGui.SameLine();
if (ImGui.Checkbox("Support Korean", ref SupportKoreanCharacters))
{
changed = true;
FontsManager.Instance.BuildFonts();
}
ImGui.SameLine();
if (ImGui.Checkbox("Support Cyrillic", ref SupportCyrillicCharacters))
{
changed = true;
FontsManager.Instance.BuildFonts();
}
}
// apply confirmation
if (_applyingIndex >= 0)
{
string[] lines = new string[] { "Are you sure you want to apply this font", "to all labels using a font with the same size?" };
var (didConfirm, didClose) = ImGuiHelper.DrawConfirmationModal("Apply to all labels?", lines);
if (didConfirm)
{
var (key, font) = Fonts.ElementAt(_applyingIndex);
List<LabelConfig> labelConfigs = ConfigurationManager.Instance.GetObjects<LabelConfig>();
foreach (LabelConfig label in labelConfigs)
{
if (label.FontID != null && Fonts.TryGetValue(label.FontID, out FontData value))
{
if (font.Size == value.Size)
{
label.FontID = key;
}
}
}
changed = true;
ConfigurationManager.Instance.SaveConfigurations(forced: true);
}
if (didConfirm || didClose)
{
_applyingIndex = -1;
}
}
// delete confirmation
if (_removingIndex >= 0)
{
string[] lines = new string[] { "Are you sure you want to remove this font?" };
var (didConfirm, didClose) = ImGuiHelper.DrawConfirmationModal("Remove custom font?", lines);
if (didConfirm)
{
Fonts.RemoveAt(_removingIndex);
FontsManager.Instance.BuildFonts();
changed = true;
}
if (didConfirm || didClose)
{
_removingIndex = -1;
}
}
ImGui.EndChild();
_fileDialogManager.Draw();
return false;
}
}
}