mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-08 20:27:36 +02:00
Completely rewrite resource load / update / remove
1. part of #468 2. fix #1245, bug introduced in 7e1c77beddf2c978fa1440e799fec4eb9554739d
This commit is contained in:
@@ -2,7 +2,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using JetBrains.Annotations;
|
||||
using Wox.Core.Plugin;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Infrastructure.Exception;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.UserSettings;
|
||||
@@ -10,13 +14,34 @@ using Wox.Plugin;
|
||||
|
||||
namespace Wox.Core.Resource
|
||||
{
|
||||
public class Internationalization : Resource
|
||||
public class Internationalization
|
||||
{
|
||||
public Settings Settings { get; set; }
|
||||
private const string DirectoryName = "Languages";
|
||||
private string DirectoryPath => Path.Combine(Constant.ProgramDirectory, DirectoryName);
|
||||
private readonly List<string> _languageDirectories = new List<string>();
|
||||
private readonly List<ResourceDictionary> _oldResources = new List<ResourceDictionary>();
|
||||
|
||||
public Internationalization()
|
||||
{
|
||||
DirectoryName = "Languages";
|
||||
var woxThemeDirectory = Path.Combine(Constant.ProgramDirectory, DirectoryName);
|
||||
_languageDirectories.Add(woxThemeDirectory);
|
||||
|
||||
foreach (var plugin in PluginManager.GetPluginsForInterface<IPluginI18n>())
|
||||
{
|
||||
var location = Assembly.GetAssembly(plugin.Plugin.GetType()).Location;
|
||||
var dir = Path.GetDirectoryName(location);
|
||||
if (dir != null)
|
||||
{
|
||||
var pluginThemeDirectory = Path.Combine(dir, DirectoryName);
|
||||
_languageDirectories.Add(pluginThemeDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"|ResourceMerger.UpdatePluginLanguages|Can't find plugin path <{location}> for <{plugin.Metadata.Name}>");
|
||||
}
|
||||
}
|
||||
|
||||
MakesureDirectoriesExist();
|
||||
}
|
||||
|
||||
@@ -37,6 +62,7 @@ namespace Wox.Core.Resource
|
||||
|
||||
public void ChangeLanguage(string languageCode)
|
||||
{
|
||||
languageCode = languageCode.NonNull();
|
||||
Language language = GetLanguageByLanguageCode(languageCode);
|
||||
ChangeLanguage(language);
|
||||
}
|
||||
@@ -58,42 +84,37 @@ namespace Wox.Core.Resource
|
||||
|
||||
public void ChangeLanguage(Language language)
|
||||
{
|
||||
if (language != null)
|
||||
language = language.NonNull();
|
||||
|
||||
var files = _languageDirectories.Select(LanguageFile).Where(f => !string.IsNullOrEmpty(f)).ToArray();
|
||||
|
||||
if (files.Length > 0)
|
||||
{
|
||||
string path = GetLanguagePath(language);
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
Settings.Language = language.LanguageCode;
|
||||
|
||||
var dicts = Application.Current.Resources.MergedDictionaries;
|
||||
foreach (var r in _oldResources)
|
||||
{
|
||||
Settings.Language = language.LanguageCode;
|
||||
ResourceMerger.UpdateResource(this);
|
||||
dicts.Remove(r);
|
||||
}
|
||||
else
|
||||
foreach (var f in files)
|
||||
{
|
||||
Log.Error($"|Internationalization.ChangeLanguage|Language path can't be found <{path}>");
|
||||
path = GetLanguagePath(AvailableLanguages.English);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
var r = new ResourceDictionary
|
||||
{
|
||||
Log.Error($"|Internationalization.ChangeLanguage|Default english language path can't be found <{path}>");
|
||||
}
|
||||
Source = new Uri(f, UriKind.Absolute)
|
||||
};
|
||||
dicts.Add(r);
|
||||
_oldResources.Add(r);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
foreach (var plugin in PluginManager.GetPluginsForInterface<IPluginI18n>())
|
||||
{
|
||||
Log.Error("|Internationalization.ChangeLanguage|Language can't be null");
|
||||
UpdatePluginMetadataTranslations(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override ResourceDictionary GetResourceDictionary()
|
||||
{
|
||||
var uri = GetLanguageFile(DirectoryPath);
|
||||
var dictionary = new ResourceDictionary
|
||||
{
|
||||
Source = new Uri(uri, UriKind.Absolute)
|
||||
};
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
public List<Language> LoadAvailableLanguages()
|
||||
{
|
||||
return AvailableLanguages.GetAvailableLanguages();
|
||||
@@ -112,14 +133,7 @@ namespace Wox.Core.Resource
|
||||
}
|
||||
}
|
||||
|
||||
private string GetLanguagePath(string languageCode)
|
||||
{
|
||||
Language language = GetLanguageByLanguageCode(languageCode);
|
||||
return GetLanguagePath(language);
|
||||
}
|
||||
|
||||
|
||||
internal void UpdatePluginMetadataTranslations(PluginPair pluginPair)
|
||||
private void UpdatePluginMetadataTranslations(PluginPair pluginPair)
|
||||
{
|
||||
var pluginI18n = pluginPair.Plugin as IPluginI18n;
|
||||
if (pluginI18n == null) return;
|
||||
@@ -134,38 +148,34 @@ namespace Wox.Core.Resource
|
||||
}
|
||||
}
|
||||
|
||||
private string GetLanguagePath(Language language)
|
||||
public string LanguageFile(string folder)
|
||||
{
|
||||
string path = Path.Combine(DirectoryPath, language.LanguageCode + ".xaml");
|
||||
if (File.Exists(path))
|
||||
if (Directory.Exists(folder))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
|
||||
public string GetLanguageFile(string folder)
|
||||
{
|
||||
if (!Directory.Exists(folder)) return string.Empty;
|
||||
|
||||
string path = Path.Combine(folder, Settings.Language + ".xaml");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
return path;
|
||||
string path = Path.Combine(folder, Settings.Language + ".xaml");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"|Internationalization.LanguageFile|Language path can't be found <{path}>");
|
||||
string english = Path.Combine(folder, "en.xaml");
|
||||
if (File.Exists(english))
|
||||
{
|
||||
return english;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"|Internationalization.LanguageFile|Default English Language path can't be found <{path}>");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string english = Path.Combine(folder, "en.xaml");
|
||||
if (File.Exists(english))
|
||||
{
|
||||
return english;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using Wox.Infrastructure;
|
||||
|
||||
namespace Wox.Core.Resource
|
||||
{
|
||||
public abstract class Resource
|
||||
{
|
||||
public string DirectoryName { get; protected set; }
|
||||
|
||||
protected string DirectoryPath => Path.Combine(Infrastructure.Constant.ProgramDirectory, DirectoryName);
|
||||
|
||||
public abstract ResourceDictionary GetResourceDictionary();
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using Wox.Core.Plugin;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Plugin;
|
||||
using Wox.Infrastructure.Exception;
|
||||
using Wox.Infrastructure.Logger;
|
||||
|
||||
namespace Wox.Core.Resource
|
||||
{
|
||||
public static class ResourceMerger
|
||||
{
|
||||
static ResourceMerger()
|
||||
{
|
||||
// remove all dictionaries defined in xaml e.g.g App.xaml
|
||||
Application.Current.Resources.MergedDictionaries.Clear();
|
||||
}
|
||||
private static void RemoveResource(string directoryName)
|
||||
{
|
||||
var dictionaries = Application.Current.Resources.MergedDictionaries;
|
||||
var invalids = dictionaries.Where(dict =>
|
||||
{
|
||||
var dir = Path.GetDirectoryName(dict.Source.AbsolutePath).NonNull();
|
||||
var invalid = dir.Contains(directoryName);
|
||||
return invalid;
|
||||
}).ToList();
|
||||
foreach (var i in invalids)
|
||||
{
|
||||
dictionaries.Remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateResource<T>(T t) where T : Core.Resource.Resource
|
||||
{
|
||||
RemoveResource(t.DirectoryName);
|
||||
Application.Current.Resources.MergedDictionaries.Add(t.GetResourceDictionary());
|
||||
}
|
||||
|
||||
internal static void UpdatePluginLanguages()
|
||||
{
|
||||
RemoveResource(Infrastructure.Constant.Plugins);
|
||||
foreach (var plugin in PluginManager.GetPluginsForInterface<IPluginI18n>())
|
||||
{
|
||||
var location = Assembly.GetAssembly(plugin.Plugin.GetType()).Location;
|
||||
var directoryName = Path.GetDirectoryName(location);
|
||||
if (directoryName != null)
|
||||
{
|
||||
var internationalization = InternationalizationManager.Instance;
|
||||
var folder = Path.Combine(directoryName, internationalization.DirectoryName);
|
||||
|
||||
var file = internationalization.GetLanguageFile(folder);
|
||||
if (!string.IsNullOrEmpty(file))
|
||||
{
|
||||
var resource = new ResourceDictionary
|
||||
{
|
||||
Source = new Uri(file, UriKind.Absolute)
|
||||
};
|
||||
Application.Current.Resources.MergedDictionaries.Add(resource);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"|ResourceMerger.UpdatePluginLanguages|Can't find plugin path <{location}> for <{plugin.Metadata.Name}>");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,15 +7,18 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.UserSettings;
|
||||
|
||||
namespace Wox.Core.Resource
|
||||
{
|
||||
public class Theme : Resource
|
||||
public class Theme
|
||||
{
|
||||
private static List<string> themeDirectories = new List<string>();
|
||||
public Settings Settings { get; set; }
|
||||
protected string DirectoryPath => Path.Combine(Constant.ProgramDirectory, DirectoryName);
|
||||
public string DirectoryName { get; protected set; }
|
||||
|
||||
public Theme()
|
||||
{
|
||||
@@ -42,40 +45,47 @@ namespace Wox.Core.Resource
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeTheme(string themeName)
|
||||
public void ChangeTheme(string theme)
|
||||
{
|
||||
string themePath = GetThemePath(themeName);
|
||||
if (string.IsNullOrEmpty(themePath))
|
||||
{
|
||||
themePath = GetThemePath("Dark");
|
||||
if (string.IsNullOrEmpty(themePath))
|
||||
{
|
||||
throw new Exception("Change theme failed");
|
||||
}
|
||||
}
|
||||
const string dark = "Dark";
|
||||
bool valid;
|
||||
|
||||
Settings.Theme = themeName;
|
||||
ResourceMerger.UpdateResource(this);
|
||||
|
||||
// Exception of FindResource can't be cathed if global exception handle is set
|
||||
if (Environment.OSVersion.Version >= new Version(6, 2))
|
||||
string path = GetThemePath(theme);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
var resource = Application.Current.TryFindResource("ThemeBlurEnabled");
|
||||
bool blur;
|
||||
if (resource is bool)
|
||||
Log.Error($"|Theme.ChangeTheme|Theme path can't be found <{path}>, use default dark theme");
|
||||
path = GetThemePath(dark);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
blur = (bool)resource;
|
||||
valid = false;
|
||||
Log.Error($"|Theme.ChangeTheme|Default theme path can't be found <{path}>");
|
||||
}
|
||||
else
|
||||
{
|
||||
blur = false;
|
||||
valid = true;
|
||||
theme = dark;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = true;
|
||||
}
|
||||
|
||||
if (valid)
|
||||
{
|
||||
Settings.Theme = theme;
|
||||
|
||||
var dicts = Application.Current.Resources.MergedDictionaries;
|
||||
// OnStartup, there is nothing to remove
|
||||
var oldResource = dicts.FirstOrDefault(d => d.Source.AbsolutePath == path) ?? new ResourceDictionary();
|
||||
dicts.Remove(oldResource);
|
||||
var newResource = GetResourceDictionary();
|
||||
dicts.Add(newResource);
|
||||
|
||||
SetBlurForWindow(Application.Current.MainWindow, blur);
|
||||
}
|
||||
}
|
||||
|
||||
public override ResourceDictionary GetResourceDictionary()
|
||||
public ResourceDictionary GetResourceDictionary()
|
||||
{
|
||||
var uri = GetThemePath(Settings.Theme);
|
||||
var dict = new ResourceDictionary
|
||||
@@ -176,17 +186,31 @@ namespace Wox.Core.Resource
|
||||
/// <summary>
|
||||
/// Sets the blur for a window via SetWindowCompositionAttribute
|
||||
/// </summary>
|
||||
/// <param name="w">window to blur</param>
|
||||
/// <param name="blur">true/false - on or off correspondingly</param>
|
||||
private void SetBlurForWindow(Window w, bool blur)
|
||||
public void SetBlurForWindow()
|
||||
{
|
||||
if (blur)
|
||||
|
||||
// Exception of FindResource can't be cathed if global exception handle is set
|
||||
if (Environment.OSVersion.Version >= new Version(6, 2))
|
||||
{
|
||||
SetWindowAccent(w, AccentState.ACCENT_ENABLE_BLURBEHIND);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowAccent(w, AccentState.ACCENT_DISABLED);
|
||||
var resource = Application.Current.TryFindResource("ThemeBlurEnabled");
|
||||
bool blur;
|
||||
if (resource is bool)
|
||||
{
|
||||
blur = (bool)resource;
|
||||
}
|
||||
else
|
||||
{
|
||||
blur = false;
|
||||
}
|
||||
|
||||
if (blur)
|
||||
{
|
||||
SetWindowAccent(Application.Current.MainWindow, AccentState.ACCENT_ENABLE_BLURBEHIND);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowAccent(Application.Current.MainWindow, AccentState.ACCENT_DISABLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user