diff --git a/Wox.Infrastructure/Storage/BinaryStorage.cs b/Wox.Infrastructure/Storage/BinaryStorage.cs
index a04434c80d..ccdd82903c 100644
--- a/Wox.Infrastructure/Storage/BinaryStorage.cs
+++ b/Wox.Infrastructure/Storage/BinaryStorage.cs
@@ -10,6 +10,7 @@ namespace Wox.Infrastructure.Storage
///
/// Stroage object using binary data
/// Normally, it has better performance, but not readable
+ /// You MUST mark implement class as Serializable
///
[Serializable]
public abstract class BinaryStorage : BaseStorage where T : class, IStorage, new()
diff --git a/Wox.Plugin.SystemPlugins/CMD/CMDStorage.cs b/Wox.Plugin.SystemPlugins/CMD/CMDStorage.cs
index cfb3a5ddc3..3695ead3c7 100644
--- a/Wox.Plugin.SystemPlugins/CMD/CMDStorage.cs
+++ b/Wox.Plugin.SystemPlugins/CMD/CMDStorage.cs
@@ -29,5 +29,6 @@ namespace Wox.Plugin.SystemPlugins.CMD
}
Save();
}
+
}
}
diff --git a/Wox/Converters/ImagePathConverter.cs b/Wox/Converters/ImagePathConverter.cs
index 4468a3acd0..20843a6864 100644
--- a/Wox/Converters/ImagePathConverter.cs
+++ b/Wox/Converters/ImagePathConverter.cs
@@ -18,7 +18,7 @@ namespace Wox.Converters
return null;
}
- return ImageLoader.Load(value.ToString());
+ return ImageLoader.ImageLoader.Load(value.ToString());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
diff --git a/Wox/ImageLoader/ImageCacheStroage.cs b/Wox/ImageLoader/ImageCacheStroage.cs
new file mode 100644
index 0000000000..88526e3e45
--- /dev/null
+++ b/Wox/ImageLoader/ImageCacheStroage.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Wox.Infrastructure.Storage;
+
+namespace Wox.ImageLoader
+{
+ [Serializable]
+ public class ImageCacheStroage : BinaryStorage
+ {
+ public int counter = 0;
+ public const int maxCached = 200;
+ public Dictionary TopUsedImages = new Dictionary();
+
+ protected override string ConfigName
+ {
+ get { return "ImageCache"; }
+ }
+
+ public void Add(string path)
+ {
+ if (TopUsedImages.ContainsKey(path))
+ {
+ TopUsedImages[path] = TopUsedImages[path] + 1 ;
+ }
+ else
+ {
+ TopUsedImages.Add(path, 1);
+ }
+
+ if (TopUsedImages.Count > maxCached)
+ {
+ TopUsedImages = TopUsedImages.OrderByDescending(o => o.Value)
+ .Take(maxCached)
+ .ToDictionary(i => i.Key, i => i.Value);
+ }
+
+ if (++counter == 30)
+ {
+ counter = 0;
+ Save();
+ }
+ }
+
+ public void Remove(string path)
+ {
+ if (TopUsedImages.ContainsKey(path))
+ {
+ TopUsedImages.Remove(path);
+ }
+ }
+ }
+}
diff --git a/Wox/Helper/ImageLoader.cs b/Wox/ImageLoader/ImageLoader.cs
similarity index 83%
rename from Wox/Helper/ImageLoader.cs
rename to Wox/ImageLoader/ImageLoader.cs
index bd01a230d6..5eccebb2b0 100644
--- a/Wox/Helper/ImageLoader.cs
+++ b/Wox/ImageLoader/ImageLoader.cs
@@ -1,17 +1,14 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Drawing;
-using System.Globalization;
using System.IO;
-using System.Linq;
using System.Runtime.InteropServices;
-using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
+using Wox.Infrastructure;
-namespace Wox.Helper
+namespace Wox.ImageLoader
{
public class ImageLoader
{
@@ -53,9 +50,42 @@ namespace Wox.Helper
return null;
}
- public static ImageSource Load(string path)
+ public static void PreloadImages()
+ {
+ //ImageCacheStroage.Instance.TopUsedImages can be changed during foreach, so we need to make a copy
+ var imageList = new Dictionary(ImageCacheStroage.Instance.TopUsedImages);
+ using (new Timeit(string.Format("Preload {0} images",imageList.Count)))
+ {
+ foreach (var image in imageList)
+ {
+ ImageSource img = Load(image.Key, false);
+ if (img != null)
+ {
+ img.Freeze(); //to make it copy to UI thread
+ if (!imageCache.ContainsKey(image.Key))
+ {
+ lock (locker)
+ {
+ if (!imageCache.ContainsKey(image.Key))
+ {
+ KeyValuePair copyedImg = image;
+ App.Window.Dispatcher.Invoke(new Action(() => imageCache.Add(copyedImg.Key, img)));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static ImageSource Load(string path,bool addToCache = true)
{
if (string.IsNullOrEmpty(path)) return null;
+ if (addToCache)
+ {
+ ImageCacheStroage.Instance.Add(path);
+ }
+
if (imageCache.ContainsKey(path))
{
return imageCache[path];
@@ -78,7 +108,7 @@ namespace Wox.Helper
}
- if (img != null)
+ if (img != null && addToCache)
{
if (!imageCache.ContainsKey(path))
{
diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs
index cfc220ff9b..753a528f4e 100644
--- a/Wox/MainWindow.xaml.cs
+++ b/Wox/MainWindow.xaml.cs
@@ -16,6 +16,7 @@ using NHotkey;
using NHotkey.Wpf;
using Wox.Commands;
using Wox.Helper;
+using Wox.ImageLoader;
using Wox.Infrastructure;
using Wox.Infrastructure.Storage;
using Wox.Infrastructure.Storage.UserSettings;
@@ -188,9 +189,22 @@ namespace Wox
Closing += MainWindow_Closing;
//since MainWIndow implement IPublicAPI, so we need to finish ctor MainWindow object before
//PublicAPI invoke in plugin init methods. E.g FolderPlugin
- ThreadPool.QueueUserWorkItem(o => Plugins.Init());
+ ThreadPool.QueueUserWorkItem(o =>
+ {
+ Thread.Sleep(50);
+ Plugins.Init();
+ });
+ ThreadPool.QueueUserWorkItem(o =>
+ {
+ Thread.Sleep(50);
+ PreLoadImages();
+ });
+ ThreadPool.QueueUserWorkItem(o => CheckUpdate());
+ }
- ThreadPool.QueueUserWorkItem(o => checkUpdate());
+ private void PreLoadImages()
+ {
+ ImageLoader.ImageLoader.PreloadImages();
}
void pnlResult_RightMouseClickEvent(Result result)
@@ -198,7 +212,7 @@ namespace Wox
ShowContextMenu(result);
}
- void checkUpdate()
+ void CheckUpdate()
{
Release release = new UpdateChecker().CheckUpgrade();
if (release != null && !UserSettingStorage.Instance.DontPromptUpdateMsg)
diff --git a/Wox/SettingWindow.xaml.cs b/Wox/SettingWindow.xaml.cs
index 6fa6b28410..4c752ad13c 100644
--- a/Wox/SettingWindow.xaml.cs
+++ b/Wox/SettingWindow.xaml.cs
@@ -482,7 +482,7 @@ namespace Wox
pluginAuthor.Text = "By: " + pair.Metadata.Author;
pluginSubTitle.Text = pair.Metadata.Description;
pluginId = pair.Metadata.ID;
- pluginIcon.Source = ImageLoader.Load(pair.Metadata.FullIcoPath);
+ pluginIcon.Source = ImageLoader.ImageLoader.Load(pair.Metadata.FullIcoPath);
}
else
{
@@ -499,7 +499,7 @@ namespace Wox
tbOpenPluginDirecoty.Visibility = Visibility.Collapsed;
pluginActionKeywordTitle.Visibility = Visibility.Collapsed;
pluginTitle.Cursor = Cursors.Arrow;
- pluginIcon.Source = ImageLoader.Load(sys.FullIcoPath);
+ pluginIcon.Source = ImageLoader.ImageLoader.Load(sys.FullIcoPath);
}
}
diff --git a/Wox/Wox.csproj b/Wox/Wox.csproj
index 0d571690fc..0dd51d0540 100644
--- a/Wox/Wox.csproj
+++ b/Wox/Wox.csproj
@@ -104,6 +104,7 @@
+
NewVersionWindow.xaml
@@ -136,7 +137,7 @@
-
+