public static void ApplyTheme(Application app, ThemeDescription theme, ApplicationMode mode) { var allLoaded = true; var loadedXamls = new List <ResourceDictionary>(); var xamlFiles = Directory.GetFiles(theme.DirectoryPath, "*.xaml", SearchOption.AllDirectories); foreach (var xamlFile in xamlFiles) { try { var xaml = Xaml.FromFile(xamlFile); if (xaml is ResourceDictionary xamlDir) { xamlDir.Source = new Uri(xamlFile, UriKind.Absolute); loadedXamls.Add(xamlDir as ResourceDictionary); } else { logger.Error($"Skipping theme file {xamlFile}, it's not resource dictionary."); } } catch (Exception e) when(!PlayniteEnvironment.ThrowAllErrors) { logger.Error(e, $"Failed to load xaml {xamlFiles}"); allLoaded = false; break; } } if (allLoaded) { loadedXamls.ForEach(a => app.Resources.MergedDictionaries.Add(a)); } }
public static bool ApplyTheme(Application app, ThemeDescription theme, ApplicationMode mode) { if ((new System.Version(theme.ThemeApiVersion).Major != ThemeApiVersion.Major)) { logger.Error($"Failed to apply {theme.Name} theme, unsupported API version {theme.ThemeApiVersion}."); return(false); } var allLoaded = true; var loadedXamls = new List <ResourceDictionary>(); var acceptableXamls = new List <string>(); var defaultRoot = $"Themes/{mode.GetDescription()}/{DefaultTheme.DirectoryName}/"; foreach (var dict in app.Resources.MergedDictionaries) { if (dict.Source.OriginalString.StartsWith("Themes") && dict.Source.OriginalString.EndsWith("xaml")) { acceptableXamls.Add(dict.Source.OriginalString.Replace(defaultRoot, "").Replace('/', '\\')); } } foreach (var accXaml in acceptableXamls) { var xamlPath = Path.Combine(theme.DirectoryPath, accXaml); if (!File.Exists(xamlPath)) { continue; } try { var xaml = Xaml.FromFile(xamlPath); if (xaml is ResourceDictionary xamlDir) { xamlDir.Source = new Uri(xamlPath, UriKind.Absolute); loadedXamls.Add(xamlDir as ResourceDictionary); } else { logger.Error($"Skipping theme file {xamlPath}, it's not resource dictionary."); } } catch (Exception e) when(!PlayniteEnvironment.ThrowAllErrors) { logger.Error(e, $"Failed to load xaml {xamlPath}"); allLoaded = false; break; } } if (allLoaded) { loadedXamls.ForEach(a => app.Resources.MergedDictionaries.Add(a)); return(true); } return(false); }
public static void SetLanguage(string language) { var dictionaries = Application.Current.Resources.MergedDictionaries; if (CurrentLanguage != SourceLanguageId) { var currentLang = dictionaries.FirstOrDefault(a => a["LanguageName"] != null && a.Source == null); if (currentLang != null) { dictionaries.Remove(currentLang); } } var langFile = Path.Combine(PlaynitePaths.LocalizationsPath, language + ".xaml"); if (File.Exists(langFile) && language != SourceLanguageId) { ResourceDictionary res = null; try { res = Xaml.FromFile <ResourceDictionary>(langFile); res.Source = new Uri(langFile, UriKind.Absolute); // Unstranslated strings are imported as empty entries by Crowdin. // We need to remove them to make sure that origina English text will be displayed instead. foreach (var key in res.Keys) { if (res[key] is string locString && locString.IsNullOrEmpty()) { res.Remove(key); } } } catch (Exception e) when(!PlayniteEnvironment.ThrowAllErrors) { logger.Error(e, $"Failed to parse localization file {langFile}"); return; } dictionaries.Add(res); ApplicationLanguageCultureInfo = new CultureInfo(language.Replace("_", "-"), false); } else { ApplicationLanguageCultureInfo = new CultureInfo("en-US", false); // english is the default language } CurrentLanguage = language; }
/// <summary> /// Set in application ressources the common ressources. /// </summary> /// <param name="pluginFolder"></param> public static void Load(string pluginFolder) { List <string> ListCommonFiles = new List <string> { Path.Combine(pluginFolder, "Resources\\Common.xaml"), Path.Combine(pluginFolder, "Resources\\LiveChartsCommon\\Common.xaml") }; foreach (string CommonFile in ListCommonFiles) { if (File.Exists(CommonFile)) { #if DEBUG logger.Debug($"PluginCommon - Load {CommonFile}"); #endif ResourceDictionary res = null; try { res = Xaml.FromFile <ResourceDictionary>(CommonFile); res.Source = new Uri(CommonFile, UriKind.Absolute); foreach (var key in res.Keys) { if (res[key] is string locString && locString.IsNullOrEmpty()) { res.Remove(key); } } } catch (Exception ex) { LogError(ex, "PluginCommon", $"Failed to parse file {CommonFile}"); return; } #if DEBUG logger.Debug($"PluginCommon - res: {JsonConvert.SerializeObject(res)}"); #endif Application.Current.Resources.MergedDictionaries.Add(res); } else { logger.Warn($"PluginCommon - File {CommonFile} not found."); return; } } }
public static List <PlayniteLanguage> GetLanguagesFromFolder(string path) { var langs = new List <PlayniteLanguage>() { new PlayniteLanguage() { Id = SourceLanguageId, LocaleString = "English" } }; if (!Directory.Exists(path)) { return(langs); } foreach (var file in Directory.GetFiles(path, "*.xaml")) { if (!Regex.IsMatch(file, "[a-zA-Z]+_[a-zA-Z]+")) { continue; } var langPath = Path.Combine(path, file); ResourceDictionary res = null; try { res = Xaml.FromFile <ResourceDictionary>(langPath); } catch (Exception e) when(!PlayniteEnvironment.ThrowAllErrors) { logger.Error(e, $"Failed to parse localization file {file}"); continue; } langs.Add(new PlayniteLanguage() { Id = Path.GetFileNameWithoutExtension(langPath), LocaleString = res["LanguageName"].ToString() }); } return(langs.OrderBy(a => a.LocaleString).ToList()); }
public static void ApplyFullscreenButtonPrompts(Application app, FullscreenButtonPrompts prompts) { if (prompts == FullscreenSettings.DefaultButtonPrompts) { var defaultXaml = $"{FullscreenSettings.DefaultButtonPrompts.ToString()}.xaml"; foreach (var dir in PlayniteApplication.CurrentNative.Resources.MergedDictionaries.ToList()) { if (dir.Source == null) { continue; } if (dir.Source.OriginalString.Contains("ButtonPrompts") && !dir.Source.OriginalString.EndsWith(defaultXaml)) { PlayniteApplication.CurrentNative.Resources.MergedDictionaries.Remove(dir); } } } else { var promptsPath = Path.Combine(ThemeManager.DefaultTheme.DirectoryPath, "Images", "ButtonPrompts"); foreach (var dir in Directory.GetDirectories(promptsPath)) { var dirInfo = new DirectoryInfo(dir); var promptXaml = Path.Combine(dir, $"{dirInfo.Name}.xaml"); if (File.Exists(promptXaml) && dirInfo.Name == prompts.ToString()) { var xaml = Xaml.FromFile(promptXaml); if (xaml is ResourceDictionary xamlDir) { xamlDir.Source = new Uri(promptXaml, UriKind.Absolute); PlayniteApplication.CurrentNative.Resources.MergedDictionaries.Add(xamlDir); } } } } }
public TestResourceProvider() { var engSource = Path.Combine(PlaynitePaths.LocalizationsPath, PlaynitePaths.EngLocSourceFileName); engStringResource = Xaml.FromFile <ResourceDictionary>(engSource); }
public static AddonLoadError ApplyTheme(Application app, ThemeManifest theme, ApplicationMode mode) { if (theme.Id.IsNullOrEmpty()) { logger.Error($"Theme {theme.Name}, doesn't have ID."); return(AddonLoadError.Uknown); } var apiVesion = mode == ApplicationMode.Desktop ? DesktopApiVersion : FullscreenApiVersion; if (!theme.ThemeApiVersion.IsNullOrEmpty()) { var themeVersion = new Version(theme.ThemeApiVersion); if (themeVersion.Major != apiVesion.Major || themeVersion > apiVesion) { logger.Error($"Failed to apply {theme.Name} theme, unsupported API version {theme.ThemeApiVersion}."); return(AddonLoadError.SDKVersion); } } var acceptableXamls = new List <string>(); var defaultRoot = $"Themes/{mode.GetDescription()}/{DefaultTheme.DirectoryName}/"; foreach (var dict in app.Resources.MergedDictionaries) { if (dict.Source.OriginalString.StartsWith(defaultRoot)) { acceptableXamls.Add(dict.Source.OriginalString.Replace(defaultRoot, "").Replace('/', '\\')); } } var allLoaded = true; foreach (var accXaml in acceptableXamls) { var xamlPath = Path.Combine(theme.DirectoryPath, accXaml); if (!File.Exists(xamlPath)) { continue; } try { var xaml = Xaml.FromFile(xamlPath); } catch (Exception e) when(!PlayniteEnvironment.ThrowAllErrors) { logger.Error(e, $"Failed to load xaml {xamlPath}"); allLoaded = false; break; } } if (!allLoaded) { return(AddonLoadError.Uknown); } try { var cursorFile = ThemeFile.GetFilePath("cursor.cur"); if (cursorFile.IsNullOrEmpty()) { cursorFile = ThemeFile.GetFilePath("cursor.ani"); } if (!cursorFile.IsNullOrEmpty()) { Mouse.OverrideCursor = new Cursor(cursorFile, true); } } catch (Exception e) when(!PlayniteEnvironment.ThrowAllErrors) { logger.Error(e, "Failed to set custom mouse cursor."); } var themeRoot = $"Themes\\{mode.GetDescription()}\\{theme.DirectoryName}\\"; // This is sad that we have to do this, but it fixes issues like #2328 // We need to remove all loaded theme resources and reload them in specific order: // default/1.xaml -> theme/1.xaml -> default/2.xaml -> theme/2.xaml etc. // // We can't just load custom theme files at the end or insert them in already loaded pool of resources // because styling with static references won't reload data from custom theme files. // That's why we also have to create new instances of default styles. foreach (var defaultRes in app.Resources.MergedDictionaries.ToList()) { if (defaultRes.Source.OriginalString.StartsWith(defaultRoot)) { app.Resources.MergedDictionaries.Remove(defaultRes); } } foreach (var themeXamlFile in acceptableXamls) { var defaultPath = Path.Combine(PlaynitePaths.ThemesProgramPath, mode.GetDescription(), "Default", themeXamlFile); var defaultXaml = Xaml.FromFile(defaultPath); if (defaultXaml is ResourceDictionary xamlDir) { xamlDir.Source = new Uri(defaultPath, UriKind.Absolute); app.Resources.MergedDictionaries.Add(xamlDir); } var xamlPath = Path.Combine(theme.DirectoryPath, themeXamlFile); if (!File.Exists(xamlPath)) { continue; } var xaml = Xaml.FromFile(xamlPath); if (xaml is ResourceDictionary themeDir) { themeDir.Source = new Uri(xamlPath, UriKind.Absolute); app.Resources.MergedDictionaries.Add(themeDir); } else { logger.Error($"Skipping theme file {xamlPath}, it's not resource dictionary."); } } return(AddonLoadError.None); }
public static void SetPluginLanguage(string pluginFolder, string language, bool DefaultLoad = false) { // Load default for missing if (!DefaultLoad) { SetPluginLanguage(pluginFolder, "LocSource", true); } var dictionaries = Application.Current.Resources.MergedDictionaries; var langFile = Path.Combine(pluginFolder, "localization\\" + language + ".xaml"); var langFileCommon = Path.Combine(pluginFolder, "localization\\Common\\" + language + ".xaml"); // Load localization common if (File.Exists(langFileCommon)) { #if DEBUG logger.Debug($"PluginCommon - Parse plugin localization file {langFileCommon}."); #endif ResourceDictionary res = null; try { res = Xaml.FromFile <ResourceDictionary>(langFileCommon); res.Source = new Uri(langFileCommon, UriKind.Absolute); foreach (var key in res.Keys) { if (res[key] is string locString && locString.IsNullOrEmpty()) { res.Remove(key); } } } catch (Exception ex) { logger.Error(ex, $"PluginCommon - Failed to parse localization file {langFileCommon}."); return; } dictionaries.Add(res); } else { logger.Warn($"PluginCommon - File {langFileCommon} not found."); } // Load localization if (File.Exists(langFile)) { #if DEBUG logger.Debug($"PluginCommon - Parse plugin localization file {langFile}."); #endif ResourceDictionary res = null; try { res = Xaml.FromFile <ResourceDictionary>(langFile); res.Source = new Uri(langFile, UriKind.Absolute); foreach (var key in res.Keys) { if (res[key] is string locString && locString.IsNullOrEmpty()) { res.Remove(key); } } } catch (Exception ex) { logger.Error(ex, $"PluginCommon - Failed to parse localization file {langFile}."); return; } dictionaries.Add(res); } else { logger.Warn($"PluginCommon - File {langFile} not found."); } }