diff --git a/Plugins/Wox.Plugin.Sys/Main.cs b/Plugins/Wox.Plugin.Sys/Main.cs index de17a1dfa6..70dbd7ddc8 100644 --- a/Plugins/Wox.Plugin.Sys/Main.cs +++ b/Plugins/Wox.Plugin.Sys/Main.cs @@ -15,7 +15,6 @@ namespace Wox.Plugin.Sys { public class Main : IPlugin, ISettingProvider, IPluginI18n { - List availableResults = new List(); private PluginInitContext context; #region DllImport @@ -47,21 +46,23 @@ namespace Wox.Plugin.Sys public Control CreateSettingPanel() { - return new SysSettings(availableResults); + var results = Commands(); + return new SysSettings(results); } public List Query(Query query) { - List results = new List(); - foreach (Result availableResult in availableResults) + var commands = Commands(); + var results = new List(); + foreach (var c in commands) { - var titleScore = StringMatcher.Score(availableResult.Title, query.Search); - var subTitleScore = StringMatcher.Score(availableResult.SubTitle, query.Search); + var titleScore = StringMatcher.Score(c.Title, query.Search); + var subTitleScore = StringMatcher.Score(c.SubTitle, query.Search); var score = Math.Max(titleScore, subTitleScore); if (score > 0) { - availableResult.Score = score; - results.Add(availableResult); + c.Score = score; + results.Add(c); } } return results; @@ -70,12 +71,12 @@ namespace Wox.Plugin.Sys public void Init(PluginInitContext context) { this.context = context; - LoadCommands(); } - private void LoadCommands() + private List Commands() { - availableResults.AddRange(new[] + var results = new List(); + results.AddRange(new[] { new Result { @@ -126,7 +127,7 @@ namespace Wox.Plugin.Sys LockWorkStation(); return true; } - }, + }, new Result { Title = "Sleep", @@ -188,6 +189,7 @@ namespace Wox.Plugin.Sys } } }); + return results; } public string GetTranslatedPluginTitle() diff --git a/Wox.Core/Plugin/PluginManager.cs b/Wox.Core/Plugin/PluginManager.cs index 472019b935..ecbf9e3905 100644 --- a/Wox.Core/Plugin/PluginManager.cs +++ b/Wox.Core/Plugin/PluginManager.cs @@ -87,9 +87,6 @@ namespace Wox.Core.Plugin } public static void InitializePlugins(IPublicAPI api) { - //load plugin i18n languages - ResourceMerger.UpdatePluginLanguages(); - API = api; Parallel.ForEach(AllPlugins, pair => { @@ -103,7 +100,6 @@ namespace Wox.Core.Plugin }); pair.Metadata.InitTime += milliseconds; Log.Info($"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>"); - InternationalizationManager.Instance.UpdatePluginMetadataTranslations(pair); }); _contextMenuPlugins = GetPluginsForInterface(); diff --git a/Wox.Core/Resource/Internationalization.cs b/Wox.Core/Resource/Internationalization.cs index cc839b8c9e..9d28430acf 100644 --- a/Wox.Core/Resource/Internationalization.cs +++ b/Wox.Core/Resource/Internationalization.cs @@ -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 _languageDirectories = new List(); + private readonly List _oldResources = new List(); public Internationalization() { - DirectoryName = "Languages"; + var woxThemeDirectory = Path.Combine(Constant.ProgramDirectory, DirectoryName); + _languageDirectories.Add(woxThemeDirectory); + + foreach (var plugin in PluginManager.GetPluginsForInterface()) + { + 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()) { - 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 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; } - } } diff --git a/Wox.Core/Resource/Resource.cs b/Wox.Core/Resource/Resource.cs deleted file mode 100644 index 92d779e257..0000000000 --- a/Wox.Core/Resource/Resource.cs +++ /dev/null @@ -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(); - } -} diff --git a/Wox.Core/Resource/ResourceMerger.cs b/Wox.Core/Resource/ResourceMerger.cs deleted file mode 100644 index 035f2164e1..0000000000 --- a/Wox.Core/Resource/ResourceMerger.cs +++ /dev/null @@ -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) 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()) - { - 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}>"); - } - - } - } - } -} \ No newline at end of file diff --git a/Wox.Core/Resource/Theme.cs b/Wox.Core/Resource/Theme.cs index 5a3ff86ac4..77c715b7b5 100644 --- a/Wox.Core/Resource/Theme.cs +++ b/Wox.Core/Resource/Theme.cs @@ -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 themeDirectories = new List(); 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 /// /// Sets the blur for a window via SetWindowCompositionAttribute /// - /// window to blur - /// true/false - on or off correspondingly - 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); + } } } diff --git a/Wox.Core/Wox.Core.csproj b/Wox.Core/Wox.Core.csproj index 18fd58e103..4e062d4f58 100644 --- a/Wox.Core/Wox.Core.csproj +++ b/Wox.Core/Wox.Core.csproj @@ -115,8 +115,6 @@ - - diff --git a/Wox/App.xaml.cs b/Wox/App.xaml.cs index a911788762..4297583468 100644 --- a/Wox/App.xaml.cs +++ b/Wox/App.xaml.cs @@ -4,8 +4,10 @@ using System.Timers; using System.Windows; using Wox.Core; using Wox.Core.Plugin; +using Wox.Core.Resource; using Wox.Helper; using Wox.Infrastructure; +using Wox.Infrastructure.Http; using Wox.Infrastructure.Image; using Wox.Infrastructure.Logger; using Wox.Infrastructure.UserSettings; @@ -58,6 +60,18 @@ namespace Wox Current.MainWindow = window; Current.MainWindow.Title = Constant.Wox; + // happlebao todo temp fix for instance code logic + // remove all dictionaries defined in xaml e.g.g App.xaml + Current.Resources.MergedDictionaries.Clear(); + // load plugin before change language, because plugin language also needs be changed + InternationalizationManager.Instance.Settings = _settings; + InternationalizationManager.Instance.ChangeLanguage(_settings.Language); + // main windows needs initialized before theme change because of blur settigns + ThemeManager.Instance.Settings = _settings; + ThemeManager.Instance.ChangeTheme(_settings.Theme); + + Http.Proxy = _settings.Proxy; + RegisterExitEvents(); AutoStartup(); @@ -68,6 +82,7 @@ namespace Wox }); } + private void AutoStartup() { if (_settings.StartWoxOnSystemStartup) diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 5b1b584105..62876d32fc 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -60,8 +60,9 @@ namespace Wox private void OnLoaded(object sender, RoutedEventArgs _) { + // todo is there a way to set blur only once? + ThemeManager.Instance.SetBlurForWindow(); WindowsInteropHelper.DisableControlBox(this); - ThemeManager.Instance.ChangeTheme(_settings.Theme); InitProgressbarAnimation(); _viewModel.PropertyChanged += (o, e) => diff --git a/Wox/ViewModel/SettingWindowViewModel.cs b/Wox/ViewModel/SettingWindowViewModel.cs index b37e405bea..c5fe028d21 100644 --- a/Wox/ViewModel/SettingWindowViewModel.cs +++ b/Wox/ViewModel/SettingWindowViewModel.cs @@ -33,11 +33,7 @@ namespace Wox.ViewModel } }; - // happlebao todo temp fix for instance code logic - InternationalizationManager.Instance.Settings = Settings; - InternationalizationManager.Instance.ChangeLanguage(Settings.Language); - ThemeManager.Instance.Settings = Settings; - Http.Proxy = Settings.Proxy; + } public Settings Settings { get; set; }