Refactoring.

This commit is contained in:
qianlifeng
2014-12-27 12:34:51 +08:00
parent ccc8d7e5cd
commit d9b2863382
14 changed files with 184 additions and 148 deletions

View File

@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using Wox.Core.Plugin;
using Wox.Helper;
namespace Wox.CommandArgs
@@ -25,7 +26,7 @@ namespace Wox.CommandArgs
MessageBox.Show("Plugin " + path + " didn't exist");
return;
}
PluginInstaller.Install(path);
PluginManager.InstallPlugin(path);
}
}
}

View File

@@ -1,38 +0,0 @@
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Data;
using System.Windows.Threading;
namespace Wox.Converters
{
public class AsyncTask : INotifyPropertyChanged
{
public AsyncTask(Func<object> valueFunc)
{
LoadValue(valueFunc);
}
private void LoadValue(Func<object> valueFunc)
{
var frame = new DispatcherFrame();
ThreadPool.QueueUserWorkItem(delegate
{
object returnValue =
AsyncValue = valueFunc();
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("AsyncValue"));
});
}
public event PropertyChangedEventHandler PropertyChanged;
public object AsyncValue
{
get;
set;
}
}
}

View File

@@ -1,216 +0,0 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json;
using Wox.Core.Plugin;
using Wox.Plugin;
namespace Wox.Helper
{
public class PluginInstaller
{
public static void Install(string path)
{
if (File.Exists(path))
{
string tempFoler = Path.Combine(Path.GetTempPath(), "wox\\plugins");
if (Directory.Exists(tempFoler))
{
Directory.Delete(tempFoler, true);
}
UnZip(path, tempFoler, true);
string iniPath = Path.Combine(tempFoler, "plugin.json");
if (!File.Exists(iniPath))
{
MessageBox.Show("Install failed: plugin config is missing");
return;
}
PluginMetadata plugin = GetMetadataFromJson(tempFoler);
if (plugin == null || plugin.Name == null)
{
MessageBox.Show("Install failed: plugin config is invalid");
return;
}
string pluginFolerPath = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Plugins");
if (!Directory.Exists(pluginFolerPath))
{
Directory.CreateDirectory(pluginFolerPath);
}
string newPluginName = plugin.Name
.Replace("/", "_")
.Replace("\\", "_")
.Replace(":", "_")
.Replace("<", "_")
.Replace(">", "_")
.Replace("?", "_")
.Replace("*", "_")
.Replace("|", "_")
+ "-" + Guid.NewGuid();
string newPluginPath = Path.Combine(pluginFolerPath,newPluginName);
string content = string.Format(
"Do you want to install following plugin?\r\n\r\nName: {0}\r\nVersion: {1}\r\nAuthor: {2}",
plugin.Name, plugin.Version, plugin.Author);
PluginPair existingPlugin = PluginManager.GetPlugin(plugin.ID);
if (existingPlugin != null)
{
content = string.Format(
"Do you want to update following plugin?\r\n\r\nName: {0}\r\nOld Version: {1}\r\nNew Version: {2}\r\nAuthor: {3}",
plugin.Name, existingPlugin.Metadata.Version, plugin.Version, plugin.Author);
}
MessageBoxResult result = MessageBox.Show(content, "Install plugin",
MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
if (existingPlugin != null && Directory.Exists(existingPlugin.Metadata.PluginDirectory))
{
//when plugin is in use, we can't delete them. That's why we need to make plugin folder a random name
File.Create(Path.Combine(existingPlugin.Metadata.PluginDirectory, "NeedDelete.txt")).Close();
}
UnZip(path, newPluginPath, true);
Directory.Delete(tempFoler, true);
//exsiting plugins may be has loaded by application,
//if we try to delelte those kind of plugins, we will get a error that indicate the
//file is been used now.
//current solution is to restart wox. Ugly.
//if (MainWindow.Initialized)
//{
// Plugins.Init();
//}
if (MessageBox.Show("You have installed plugin " + plugin.Name + " successfully.\r\n Restart Wox to take effect?", "Install plugin",
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C ping 127.0.0.1 -n 1 && \"" +
System.Windows.Forms.Application.ExecutablePath + "\"";
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
App.Window.CloseApp();
}
}
}
}
private static PluginMetadata GetMetadataFromJson(string pluginDirectory)
{
string configPath = Path.Combine(pluginDirectory, "plugin.json");
PluginMetadata metadata;
if (!File.Exists(configPath))
{
return null;
}
try
{
metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath));
metadata.PluginType = PluginType.User;
metadata.PluginDirectory = pluginDirectory;
}
catch (Exception)
{
string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath);
#if (DEBUG)
{
throw new Exception(error);
}
#endif
return null;
}
if (!AllowedLanguage.IsAllowed(metadata.Language))
{
string error = string.Format("Parse plugin config {0} failed: invalid language {1}", configPath,
metadata.Language);
#if (DEBUG)
{
throw new Exception(error);
}
#endif
return null;
}
if (!File.Exists(metadata.ExecuteFilePath))
{
string error = string.Format("Parse plugin config {0} failed: ExecuteFile {1} didn't exist", configPath,
metadata.ExecuteFilePath);
#if (DEBUG)
{
throw new Exception(error);
}
#endif
return null;
}
return metadata;
}
/// <summary>
/// unzip
/// </summary>
/// <param name="zipedFile">The ziped file.</param>
/// <param name="strDirectory">The STR directory.</param>
/// <param name="overWrite">overwirte</param>
private static void UnZip(string zipedFile, string strDirectory, bool overWrite)
{
if (strDirectory == "")
strDirectory = Directory.GetCurrentDirectory();
if (!strDirectory.EndsWith("\\"))
strDirectory = strDirectory + "\\";
using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipedFile)))
{
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
{
string directoryName = "";
string pathToZip = "";
pathToZip = theEntry.Name;
if (pathToZip != "")
directoryName = Path.GetDirectoryName(pathToZip) + "\\";
string fileName = Path.GetFileName(pathToZip);
Directory.CreateDirectory(strDirectory + directoryName);
if (fileName != "")
{
if ((File.Exists(strDirectory + directoryName + fileName) && overWrite) || (!File.Exists(strDirectory + directoryName + fileName)))
{
using (FileStream streamWriter = File.Create(strDirectory + directoryName + fileName))
{
byte[] data = new byte[2048];
while (true)
{
int size = s.Read(data, 0, data.Length);
if (size > 0)
streamWriter.Write(data, 0, size);
else
break;
}
streamWriter.Close();
}
}
}
}
s.Close();
}
}
}
}

View File

@@ -13,7 +13,6 @@ namespace Wox.ImageLoader
public class ImageLoader
{
private static readonly Dictionary<string, ImageSource> imageCache = new Dictionary<string, ImageSource>();
private static object locker = new object();
private static readonly List<string> imageExts = new List<string>
{
@@ -54,23 +53,20 @@ namespace Wox.ImageLoader
{
//ImageCacheStroage.Instance.TopUsedImages can be changed during foreach, so we need to make a copy
var imageList = new Dictionary<string, int>(ImageCacheStroage.Instance.TopUsedImages);
using (new Timeit(string.Format("Preload {0} images",imageList.Count)))
using (new Timeit(string.Format("Preload {0} images", imageList.Count)))
{
foreach (var image in imageList)
{
ImageSource img = Load(image.Key, false);
if (img != null)
if (!imageCache.ContainsKey(image.Key))
{
img.Freeze(); //to make it copy to UI thread
if (!imageCache.ContainsKey(image.Key))
ImageSource img = Load(image.Key, false);
if (img != null)
{
lock (locker)
img.Freeze(); //to make it copy to UI thread
if (!imageCache.ContainsKey(image.Key))
{
if (!imageCache.ContainsKey(image.Key))
{
KeyValuePair<string, int> copyedImg = image;
App.Window.Dispatcher.Invoke(new Action(() => imageCache.Add(copyedImg.Key, img)));
}
KeyValuePair<string, int> copyedImg = image;
App.Window.Dispatcher.Invoke(new Action(() => imageCache.Add(copyedImg.Key, img)));
}
}
}
@@ -78,7 +74,7 @@ namespace Wox.ImageLoader
}
}
public static ImageSource Load(string path,bool addToCache = true)
public static ImageSource Load(string path, bool addToCache = true)
{
if (string.IsNullOrEmpty(path)) return null;
if (addToCache)
@@ -112,13 +108,7 @@ namespace Wox.ImageLoader
{
if (!imageCache.ContainsKey(path))
{
lock (locker)
{
if (!imageCache.ContainsKey(path))
{
imageCache.Add(path, img);
}
}
imageCache.Add(path, img);
}
}

View File

@@ -122,7 +122,7 @@ namespace Wox
public void InstallPlugin(string path)
{
Dispatcher.Invoke(new Action(() => PluginInstaller.Install(path)));
Dispatcher.Invoke(new Action(() => PluginManager.InstallPlugin(path)));
}
public void ReloadPlugins()
@@ -172,14 +172,8 @@ namespace Wox
pnlResult.RightMouseClickEvent += pnlResult_RightMouseClickEvent;
ThreadPool.SetMaxThreads(30, 10);
try
{
SetTheme(UserSettingStorage.Instance.Theme);
}
catch (Exception)
{
SetTheme(UserSettingStorage.Instance.Theme = "Dark");
}
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
SetHotkey(UserSettingStorage.Instance.Hotkey, OnHotkey);
SetCustomPluginHotkey();
@@ -676,44 +670,6 @@ namespace Wox
}
}
public void SetTheme(string themeName)
{
var dict = new ResourceDictionary
{
Source = new Uri(Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Themes\\" + themeName + ".xaml"), UriKind.Absolute)
};
Style queryBoxStyle = dict["QueryBoxStyle"] as Style;
if (queryBoxStyle != null)
{
queryBoxStyle.Setters.Add(new Setter(TextBox.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.QueryBoxFont)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStyle)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontWeight)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStretch)));
}
Style resultItemStyle = dict["ItemTitleStyle"] as Style;
Style resultSubItemStyle = dict["ItemSubTitleStyle"] as Style;
Style resultItemSelectedStyle = dict["ItemTitleSelectedStyle"] as Style;
Style resultSubItemSelectedStyle = dict["ItemSubTitleSelectedStyle"] as Style;
if (resultItemStyle != null && resultSubItemStyle != null && resultSubItemSelectedStyle != null && resultItemSelectedStyle != null)
{
Setter fontFamily = new Setter(TextBlock.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.ResultItemFont));
Setter fontStyle = new Setter(TextBlock.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStyle));
Setter fontWeight = new Setter(TextBlock.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontWeight));
Setter fontStretch = new Setter(TextBlock.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStretch));
Setter[] setters = new Setter[] { fontFamily, fontStyle, fontWeight, fontStretch };
Array.ForEach(new Style[] { resultItemStyle, resultSubItemStyle, resultItemSelectedStyle, resultSubItemSelectedStyle }, o => Array.ForEach(setters, p => o.Setters.Add(p)));
}
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(dict);
this.Opacity = this.AllowsTransparency ? UserSettingStorage.Instance.Opacity : 1;
}
public bool ShellRun(string cmd, bool runAsAdministrator = false)
{
try
@@ -739,7 +695,7 @@ namespace Wox
string[] files = (string[])e.Data.GetData(System.Windows.DataFormats.FileDrop);
if (files[0].ToLower().EndsWith(".wox"))
{
PluginInstaller.Install(files[0]);
PluginManager.InstallPlugin(files[0]);
}
else
{

View File

@@ -172,8 +172,7 @@ namespace Wox
}
//PreviewPanel
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
#endregion
#region Plugin
@@ -366,7 +365,7 @@ namespace Wox
private void ThemeComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
string themeName = themeComboBox.SelectedItem.ToString();
MainWindow.SetTheme(themeName);
ThemeManager.ChangeTheme(themeName);
UserSettingStorage.Instance.Theme = themeName;
UserSettingStorage.Instance.Save();
}
@@ -379,7 +378,7 @@ namespace Wox
this.cbQueryBoxFontFaces.SelectedItem = ((FontFamily)cbQueryBoxFont.SelectedItem).ChooseRegularFamilyTypeface();
UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
}
private void CbQueryBoxFontFaces_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -399,7 +398,7 @@ namespace Wox
UserSettingStorage.Instance.QueryBoxFontWeight = typeface.Weight.ToString();
UserSettingStorage.Instance.QueryBoxFontStyle = typeface.Style.ToString();
UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
}
}
@@ -411,7 +410,7 @@ namespace Wox
this.cbResultItemFontFaces.SelectedItem = ((FontFamily)cbResultItemFont.SelectedItem).ChooseRegularFamilyTypeface();
UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
}
private void CbResultItemFontFaces_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -422,8 +421,6 @@ namespace Wox
{
if (cbResultItemFontFaces.Items.Count > 0)
cbResultItemFontFaces.SelectedIndex = 0;
return;
}
else
{
@@ -431,7 +428,7 @@ namespace Wox
UserSettingStorage.Instance.ResultItemFontWeight = typeface.Weight.ToString();
UserSettingStorage.Instance.ResultItemFontStyle = typeface.Style.ToString();
UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
}
}
@@ -445,7 +442,7 @@ namespace Wox
else
PreviewMainPanel.Opacity = 1;
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
}
#endregion

104
Wox/ThemeManager.cs Normal file
View File

@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Wox.Helper;
using Wox.Infrastructure.Storage.UserSettings;
namespace Wox
{
internal class ThemeManager
{
private static List<string> themeDirectories = new List<string>();
static ThemeManager()
{
themeDirectories.Add(
Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Themes"));
string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
if (userProfilePath != null)
{
themeDirectories.Add(Path.Combine(Path.Combine(userProfilePath, ".Wox"), "Themes"));
}
MakesureThemeDirectoriesExist();
}
private static void MakesureThemeDirectoriesExist()
{
foreach (string pluginDirectory in themeDirectories)
{
if (!Directory.Exists(pluginDirectory))
{
Directory.CreateDirectory(pluginDirectory);
}
}
}
public static void ChangeTheme(string themeName)
{
string themePath = GetThemePath(themeName);
if (string.IsNullOrEmpty(themePath))
{
themePath = GetThemePath("Dark");
if (string.IsNullOrEmpty(themePath))
{
throw new Exception("Change theme failed");
}
}
var dict = new ResourceDictionary
{
Source = new Uri(themePath, UriKind.Absolute)
};
Style queryBoxStyle = dict["QueryBoxStyle"] as Style;
if (queryBoxStyle != null)
{
queryBoxStyle.Setters.Add(new Setter(TextBox.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.QueryBoxFont)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStyle)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontWeight)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStretch)));
}
Style resultItemStyle = dict["ItemTitleStyle"] as Style;
Style resultSubItemStyle = dict["ItemSubTitleStyle"] as Style;
Style resultItemSelectedStyle = dict["ItemTitleSelectedStyle"] as Style;
Style resultSubItemSelectedStyle = dict["ItemSubTitleSelectedStyle"] as Style;
if (resultItemStyle != null && resultSubItemStyle != null && resultSubItemSelectedStyle != null && resultItemSelectedStyle != null)
{
Setter fontFamily = new Setter(TextBlock.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.ResultItemFont));
Setter fontStyle = new Setter(TextBlock.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStyle));
Setter fontWeight = new Setter(TextBlock.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontWeight));
Setter fontStretch = new Setter(TextBlock.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStretch));
Setter[] setters = new Setter[] { fontFamily, fontStyle, fontWeight, fontStretch };
Array.ForEach(new Style[] { resultItemStyle, resultSubItemStyle, resultItemSelectedStyle, resultSubItemSelectedStyle }, o => Array.ForEach(setters, p => o.Setters.Add(p)));
}
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(dict);
}
private static string GetThemePath(string themeName)
{
foreach (string themeDirectory in themeDirectories)
{
string path = Path.Combine(themeDirectory, themeName + ".xaml");
if (File.Exists(path))
{
return path;
}
}
return string.Empty;
}
}
}

View File

@@ -106,6 +106,7 @@
<ItemGroup>
<Compile Include="ImageLoader\ImageCacheStroage.cs" />
<Compile Include="Storage\UserSelectedRecordStorage.cs" />
<Compile Include="ThemeManager.cs" />
<Compile Include="Update\NewVersionWindow.xaml.cs">
<DependentUpon>NewVersionWindow.xaml</DependentUpon>
</Compile>
@@ -125,7 +126,6 @@
<Compile Include="CommandArgs\PluginDebuggerCommandArg.cs" />
<Compile Include="CommandArgs\QueryCommandArg.cs" />
<Compile Include="CommandArgs\ReloadPluginCommandArg.cs" />
<Compile Include="Converters\AsyncConverter.cs" />
<Compile Include="Converters\ConvertorBase.cs" />
<Compile Include="Helper\DataWebRequestFactory.cs" />
<Compile Include="Helper\ErrorReporting\ErrorReporting.cs" />
@@ -145,7 +145,6 @@
</Compile>
<Compile Include="Helper\DispatcherExtensions.cs" />
<Compile Include="Helper\DWMDropShadow.cs" />
<Compile Include="Helper\PluginInstaller.cs" />
<Compile Include="HotkeyControl.xaml.cs">
<DependentUpon>HotkeyControl.xaml</DependentUpon>
</Compile>
@@ -202,11 +201,6 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<None Include="Themes\Dark.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Themes\Light.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -227,6 +221,10 @@
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<Page Include="Themes\Dark.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Update\NewVersionWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>