VRCMelonAssistant/ModAssistant/Classes/Themes.cs

123 lines
5.6 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.IO;
using System.Windows.Media;
2020-02-08 12:55:01 +13:00
using ModAssistant.Pages;
2020-02-08 13:46:20 +13:00
using System.Xml;
using System.Windows.Markup;
namespace ModAssistant
{
public class Themes
{
public static string LoadedTheme { get; private set; }
2020-02-03 19:53:12 +13:00
public static List<string> LoadedThemes { get => loadedThemes.Keys.ToList(); }
2020-02-08 12:55:01 +13:00
public static string ThemeDirectory => $"{Environment.CurrentDirectory}/Themes";
private static Dictionary<string, ResourceDictionary> loadedThemes = new Dictionary<string, ResourceDictionary>();
private static List<string> preInstalledThemes = new List<string> { "Light", "Dark" };
public static void LoadThemes()
{
loadedThemes.Clear();
foreach (string localTheme in preInstalledThemes)
{
ResourceDictionary theme = LoadTheme(localTheme, true);
loadedThemes.Add(localTheme, theme);
}
2020-02-08 12:55:01 +13:00
if (Directory.Exists(ThemeDirectory))
{
2020-02-08 12:55:01 +13:00
foreach (string file in Directory.EnumerateFiles(ThemeDirectory))
{
FileInfo info = new FileInfo(file);
//Ignore Themes without the xaml extension and ignore themes with the same names as others.
//If requests are made I can instead make a Theme class that splits the pre-installed themes from
//user-made ones so that one more user-made Light/Dark theme can be added.
MessageBox.Show(info.Extension);
if (info.Extension.ToLower().Contains("xaml"))
{
string name = info.Name.Split('.').First();
MessageBox.Show(name);
ResourceDictionary theme = LoadTheme(name);
if (theme != null)
{
loadedThemes.Add(name, theme);
}
}
}
//MessageBox.Show($"(DEBUG) Loaded {loadedThemes.Count - 2} themes from Themes folder.");
}
2020-02-08 12:55:01 +13:00
if (Options.Instance != null && Options.Instance.ApplicationThemeComboBox != null)
{
2020-02-08 12:55:01 +13:00
Options.Instance.ApplicationThemeComboBox.ItemsSource = LoadedThemes;
Options.Instance.ApplicationThemeComboBox.SelectedIndex = LoadedThemes.IndexOf(LoadedTheme);
}
}
private static ResourceDictionary LoadTheme(string name, bool localUri = false)
{
string location = $"{Environment.CurrentDirectory}/Themes/{name}.xaml";
if (!File.Exists(location) && !localUri) return null;
if (localUri) location = $"Themes/{name}.xaml";
Uri uri = new Uri(location, localUri ? UriKind.Relative : UriKind.Absolute);
ResourceDictionary dictionary = new ResourceDictionary();
dictionary.Source = uri;
return dictionary;
}
public static void ApplyTheme(string theme, FrameworkElement element)
{
ResourceDictionary newTheme = loadedThemes[theme];
if (newTheme != null)
{
Application.Current.Resources.MergedDictionaries.RemoveAt(0);
LoadedTheme = theme;
Application.Current.Resources.MergedDictionaries.Insert(0, newTheme);
ReloadIcons(element);
}
else throw new ArgumentException($"{theme} does not exist.");
}
private static void ReloadIcons(FrameworkElement element)
{
ResourceDictionary icons = Application.Current.Resources.MergedDictionaries.First(x => x.Source.ToString() == "Resources/Icons.xaml");
ChangeColor(element, icons, "AboutIconColor", "heartDrawingGroup");
ChangeColor(element, icons, "InfoIconColor", "info_circleDrawingGroup");
ChangeColor(element, icons, "OptionsIconColor", "cogDrawingGroup");
ChangeColor(element, icons, "ModsIconColor", "microchipDrawingGroup");
}
private static void ChangeColor(FrameworkElement element, ResourceDictionary icons, string ResourceColorName, string DrawingGroupName)
{
element.Resources[ResourceColorName] = loadedThemes[LoadedTheme][ResourceColorName];
((GeometryDrawing)((DrawingGroup)icons[DrawingGroupName]).Children[0]).Brush = (Brush)element.Resources[ResourceColorName];
}
2020-02-08 13:46:20 +13:00
public static void WriteThemeToDisk(string themeName)
{
if (!Directory.Exists(ThemeDirectory))
{
Directory.CreateDirectory(ThemeDirectory);
}
if (!File.Exists($@"{ThemeDirectory}\\{themeName}.xaml"))
{
//Store a local copy of the theme to prevent exceptions trying to access the saved copy while it's being written to.
2020-02-08 13:46:20 +13:00
ResourceDictionary dictionary = LoadTheme(themeName, true);
loadedThemes.Add(themeName, dictionary);
Options.Instance.ApplicationThemeComboBox.ItemsSource = LoadedThemes;
2020-02-08 13:46:20 +13:00
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create($@"{ThemeDirectory}\\{themeName}.xaml", settings);
XamlWriter.Save(dictionary, writer);
MainWindow.Instance.MainText = $"Template theme \"{themeName}\" saved to Themes folder.";
}
else MessageBox.Show("Template theme already exists!");
}
}
}