Improve instant search ue

This commit is contained in:
qianlifeng 2015-02-04 23:16:41 +08:00
parent 5d9a94466a
commit 1d3f1fd7d0
23 changed files with 503 additions and 367 deletions

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
@ -20,6 +21,9 @@ namespace Wox.Plugin.CMD
public List<Result> Query(Query query)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List<Result> results = new List<Result>();
List<Result> pushedResults = new List<Result>();
if (query.Search == ">")
@ -76,6 +80,8 @@ namespace Wox.Plugin.CMD
catch (Exception) { }
}
stopwatch.Stop();
DebugHelper.WriteLine("CMD:" + stopwatch.ElapsedMilliseconds + "ms");
return results;
}

View File

@ -326,8 +326,6 @@ namespace Wox.Plugin.ControlPanel
private static bool EnumRes(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam)
{
//Debug.WriteLine("Type: " + GET_RESOURCE_NAME(lpszType));
//Debug.WriteLine("Name: " + GET_RESOURCE_NAME(lpszName));
defaultIconPtr = lpszName;
return false;
}

View File

@ -16,7 +16,7 @@ namespace Wox.Plugin.Folder
public Control CreateSettingPanel()
{
return new FileSystemSettings(context);
return new FileSystemSettings(context.API);
}
public void Init(PluginInitContext context)
@ -34,9 +34,36 @@ namespace Wox.Plugin.Folder
void API_ResultItemDropEvent(Result result, IDataObject dropObject, DragEventArgs e)
{
if (dropObject.GetDataPresent(DataFormats.FileDrop))
{
HanldeFilesDrop(result, dropObject);
}
e.Handled = true;
}
private void HanldeFilesDrop(Result targetResult, IDataObject dropObject)
{
List<string> files = ((string[])dropObject.GetData(DataFormats.FileDrop, false)).ToList();
context.API.ShowContextMenu(context.CurrentPluginMetadata, GetContextMenusForFileDrop(targetResult, files));
}
private static List<Result> GetContextMenusForFileDrop(Result targetResult, List<string> files)
{
List<Result> contextMenus = new List<Result>();
string folderPath = ((FolderLink) targetResult.ContextData).Path;
contextMenus.Add(new Result()
{
Title = "Copy to this folder",
IcoPath = "Images/copy.png",
Action = _ =>
{
MessageBox.Show("Copy");
return true;
}
});
return contextMenus;
}
private void ApiBackKeyDownEvent(WoxKeyDownEventArgs e)
{
string query = e.Query;
@ -84,7 +111,8 @@ namespace Wox.Plugin.Folder
}
context.API.ChangeQuery(item.Path);
return false;
}
},
ContextData = item
}).ToList();
if (driverNames != null && !driverNames.Any(input.StartsWith))
@ -98,9 +126,7 @@ namespace Wox.Plugin.Folder
results.AddRange(QueryInternal_Directory_Exists(input));
return results;
}
private void InitialDriverList()
} private void InitialDriverList()
{
if (driverNames == null)
{

View File

@ -13,11 +13,11 @@ namespace Wox.Plugin.Folder
/// </summary>
public partial class FileSystemSettings : UserControl
{
PluginInitContext context;
private IPublicAPI woxAPI;
public FileSystemSettings(PluginInitContext context)
public FileSystemSettings(IPublicAPI woxAPI)
{
this.context = context;
this.woxAPI = woxAPI;
InitializeComponent();
lbxFolders.ItemsSource = FolderStorage.Instance.FolderLinks;
}
@ -27,7 +27,7 @@ namespace Wox.Plugin.Folder
var selectedFolder = lbxFolders.SelectedItem as FolderLink;
if (selectedFolder != null)
{
string msg = string.Format(context.API.GetTranslation("wox_plugin_folder_delete_folder_link"), selectedFolder.Path);
string msg = string.Format(woxAPI.GetTranslation("wox_plugin_folder_delete_folder_link"), selectedFolder.Path);
if (MessageBox.Show(msg, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
@ -37,7 +37,7 @@ namespace Wox.Plugin.Folder
}
else
{
string warning = context.API.GetTranslation("wox_plugin_folder_select_folder_link_warning");
string warning = woxAPI.GetTranslation("wox_plugin_folder_select_folder_link_warning");
MessageBox.Show(warning);
}
}
@ -61,7 +61,7 @@ namespace Wox.Plugin.Folder
}
else
{
string warning = context.API.GetTranslation("wox_plugin_folder_select_folder_link_warning");
string warning = woxAPI.GetTranslation("wox_plugin_folder_select_folder_link_warning");
MessageBox.Show(warning);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 B

View File

@ -71,6 +71,9 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<None Include="Images\copy.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<Content Include="Languages\en.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

View File

@ -2,6 +2,7 @@
using System.Diagnostics;
using System.IO;
using System.Threading;
using Wox.Infrastructure;
namespace Wox.Plugin.Program
{
@ -15,7 +16,7 @@ namespace Wox.Plugin.Program
if (watchedPath.Contains(path)) return;
if (!Directory.Exists(path))
{
Debug.WriteLine(string.Format("FileChangeWatcher: {0} doesn't exist", path),"WoxDebug");
DebugHelper.WriteLine(string.Format("FileChangeWatcher: {0} doesn't exist", path));
return;
}

View File

@ -108,16 +108,17 @@ namespace Wox.Plugin.Program
{
programs = ProgramCacheStorage.Instance.Programs;
}
Debug.WriteLine(string.Format("Preload {0} programs from cache", programs.Count), "Wox");
DebugHelper.WriteLine(string.Format("Preload {0} programs from cache", programs.Count));
using (new Timeit("Program Index"))
{
IndexPrograms();
}
}
void API_ResultItemDropEvent(Result result, IDataObject dropObject, DragEventArgs args)
void API_ResultItemDropEvent(Result result, IDataObject dropObject, DragEventArgs e)
{
args.Handled = true;
e.Handled = true;
}
public static void IndexPrograms()

View File

@ -21,7 +21,7 @@ namespace Wox.Core.Plugin
{
public const string ActionKeywordWildcardSign = "*";
private static List<PluginMetadata> pluginMetadatas;
private static List<IInstantSearch> instantSearches = new List<IInstantSearch>();
private static List<KeyValuePair<PluginMetadata,IInstantSearch>> instantSearches;
public static String DebuggerMode { get; private set; }
@ -98,7 +98,10 @@ namespace Wox.Core.Plugin
});
}
ThreadPool.QueueUserWorkItem(o =>
{
LoadInstantSearches();
});
}
public static void InstallPlugin(string path)
@ -146,12 +149,38 @@ namespace Wox.Core.Plugin
public static bool IsInstantSearch(string query)
{
return LoadInstantSearches().Any(o => o.IsInstantSearch(query));
return LoadInstantSearches().Any(o => o.Value.IsInstantSearch(query));
}
private static List<IInstantSearch> LoadInstantSearches()
public static bool IsInstantSearchPlugin(PluginMetadata pluginMetadata)
{
if (instantSearches.Count > 0) return instantSearches;
//todo:to improve performance, any instant search plugin that takes long than 200ms will not consider a instant plugin anymore
return pluginMetadata.Language.ToUpper() == AllowedLanguage.CSharp &&
LoadInstantSearches().Any(o => o.Key.ID == pluginMetadata.ID);
}
internal static void ExecutePluginQuery(PluginPair pair, Query query)
{
try
{
List<Result> results = pair.Plugin.Query(query) ?? new List<Result>();
results.ForEach(o =>
{
o.PluginID = pair.Metadata.ID;
});
API.PushResults(query, pair.Metadata, results);
}
catch (System.Exception e)
{
throw new WoxPluginException(pair.Metadata.Name, e);
}
}
private static List<KeyValuePair<PluginMetadata,IInstantSearch>> LoadInstantSearches()
{
if (instantSearches != null) return instantSearches;
instantSearches = new List<KeyValuePair<PluginMetadata, IInstantSearch>>();
List<PluginMetadata> CSharpPluginMetadatas = pluginMetadatas.Where(o => o.Language.ToUpper() == AllowedLanguage.CSharp.ToUpper()).ToList();
foreach (PluginMetadata metadata in CSharpPluginMetadatas)
@ -167,7 +196,7 @@ namespace Wox.Core.Plugin
foreach (Type type in types)
{
instantSearches.Add(Activator.CreateInstance(type) as IInstantSearch);
instantSearches.Add(new KeyValuePair<PluginMetadata, IInstantSearch>(metadata,Activator.CreateInstance(type) as IInstantSearch));
}
}
catch (System.Exception e)

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using Wox.Infrastructure;
using Wox.Plugin;
namespace Wox.Core.Plugin.QueryDispatcher
{
public abstract class BaseQueryDispatcher : IQueryDispatcher
{
protected abstract List<PluginPair> GetPlugins(Query query);
public void Dispatch(Query query)
{
foreach (PluginPair pair in GetPlugins(query))
{
PluginPair localPair = pair;
if (query.IsIntantQuery && PluginManager.IsInstantSearchPlugin(pair.Metadata))
{
DebugHelper.WriteLine(string.Format("Plugin {0} is executing instant search.", pair.Metadata.Name));
using (new Timeit(" => instant search took: "))
{
PluginManager.ExecutePluginQuery(localPair, query);
}
}
else
{
ThreadPool.QueueUserWorkItem(state =>
{
PluginManager.ExecutePluginQuery(localPair, query);
});
}
}
}
}
}

View File

@ -8,34 +8,14 @@ using Wox.Plugin;
namespace Wox.Core.Plugin.QueryDispatcher
{
public class SystemPluginQueryDispatcher : IQueryDispatcher
public class SystemPluginQueryDispatcher : BaseQueryDispatcher
{
private IEnumerable<PluginPair> allSytemPlugins = PluginManager.AllPlugins.Where(o => PluginManager.IsSystemPlugin(o.Metadata));
private readonly List<PluginPair> allSytemPlugins =
PluginManager.AllPlugins.Where(o => PluginManager.IsSystemPlugin(o.Metadata)).ToList();
public void Dispatch(Query query)
protected override List<PluginPair> GetPlugins(Query query)
{
var queryPlugins = allSytemPlugins;
foreach (PluginPair pair in queryPlugins)
{
PluginPair pair1 = pair;
ThreadPool.QueueUserWorkItem(state =>
{
try
{
List<Result> results = pair1.Plugin.Query(query);
results.ForEach(o =>
{
o.PluginID = pair1.Metadata.ID;
});
PluginManager.API.PushResults(query, pair1.Metadata, results);
}
catch (System.Exception e)
{
throw new WoxPluginException(pair1.Metadata.Name,e);
}
});
}
return allSytemPlugins;
}
}
}

View File

@ -9,38 +9,29 @@ using Wox.Plugin;
namespace Wox.Core.Plugin.QueryDispatcher
{
public class UserPluginQueryDispatcher : IQueryDispatcher
public class UserPluginQueryDispatcher : BaseQueryDispatcher
{
public void Dispatch(Query query)
protected override List<PluginPair> GetPlugins(Query query)
{
List<PluginPair> plugins = new List<PluginPair>();
//only first plugin that matches action keyword will get executed
PluginPair userPlugin = PluginManager.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == query.GetActionKeyword());
if (userPlugin != null && !string.IsNullOrEmpty(userPlugin.Metadata.ActionKeyword))
if (userPlugin != null)
{
var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == userPlugin.Metadata.ID);
var customizedPluginConfig = UserSettingStorage.Instance.
CustomizedPluginConfigs.FirstOrDefault(o => o.ID == userPlugin.Metadata.ID);
if (customizedPluginConfig != null && customizedPluginConfig.Disabled)
{
//need to stop the loading animation
PluginManager.API.StopLoadingBar();
return;
}
else
{
plugins.Add(userPlugin);
}
}
ThreadPool.QueueUserWorkItem(t =>
{
try
{
List<Result> results = userPlugin.Plugin.Query(query) ?? new List<Result>();
results.ForEach(o =>
{
o.PluginID = userPlugin.Metadata.ID;
});
PluginManager.API.PushResults(query, userPlugin.Metadata, results);
}
catch (System.Exception e)
{
throw new WoxPluginException(userPlugin.Metadata.Name, e);
}
});
}
return plugins;
}
}
}

View File

@ -69,6 +69,7 @@
<Compile Include="Exception\WoxI18nException.cs" />
<Compile Include="Exception\WoxJsonRPCException.cs" />
<Compile Include="Exception\WoxPluginException.cs" />
<Compile Include="Plugin\QueryDispatcher\BaseQueryDispatcher.cs" />
<Compile Include="Updater\Release.cs" />
<Compile Include="Updater\UpdaterManager.cs" />
<Compile Include="Updater\WoxUpdateSource.cs" />

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace Wox.Infrastructure
{
public static class DebugHelper
{
public static void WriteLine(string msg)
{
Debug.WriteLine(msg);
}
}
}

View File

@ -855,7 +855,7 @@
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="Debugger">
<xs:complexType name="DebugHelper">
<xs:complexContent>
<xs:extension base="Target">
<xs:choice minOccurs="0" maxOccurs="unbounded">

View File

@ -20,7 +20,7 @@ namespace Wox.Infrastructure
public void Dispose()
{
stopwatch.Stop();
Debug.WriteLine(name + ":" + stopwatch.ElapsedMilliseconds + "ms","Wox");
DebugHelper.WriteLine(name + ":" + stopwatch.ElapsedMilliseconds + "ms");
}
}
}

View File

@ -58,6 +58,7 @@
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="DebugHelper.cs" />
<Compile Include="Hotkey\InterceptKeys.cs" />
<Compile Include="Hotkey\KeyEvent.cs" />
<Compile Include="Logger\Log.cs" />

View File

@ -17,6 +17,12 @@ namespace Wox.Plugin
/// <param name="results"></param>
void PushResults(Query query, PluginMetadata plugin, List<Result> results);
/// <summary>
/// Show context menu with giving results
/// </summary>
/// <param name="results"></param>
void ShowContextMenu(PluginMetadata plugin, List<Result> results);
/// <summary>
/// Execute command
/// a replacement to RUN(win+r) function

View File

@ -33,6 +33,8 @@ namespace Wox.Plugin
return string.Empty;
}
internal bool IsIntantQuery { get; set; }
/// <summary>
/// Return first search split by space if it has
/// </summary>

View File

@ -73,6 +73,11 @@ namespace Wox.Plugin
/// </summary>
public List<Result> ContextMenu { get; set; }
/// <summary>
/// Additional data associate with this result
/// </summary>
public object ContextData { get; set; }
/// <summary>
/// Plugin ID that generate this result
/// </summary>

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
@ -79,18 +80,22 @@ namespace Wox.ImageLoader
public static ImageSource Load(string path, bool addToCache = true)
{
Stopwatch sw = new Stopwatch();
sw.Start();
if (string.IsNullOrEmpty(path)) return null;
if (addToCache)
{
ImageCacheStroage.Instance.Add(path);
}
ImageSource img = null;
if (imageCache.ContainsKey(path))
{
return imageCache[path];
img = imageCache[path];
}
ImageSource img = null;
else
{
string ext = Path.GetExtension(path).ToLower();
if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
@ -114,7 +119,10 @@ namespace Wox.ImageLoader
imageCache.Add(path, img);
}
}
}
sw.Stop();
DebugHelper.WriteLine(string.Format("Loading image path: {0} - {1}ms",path,sw.ElapsedMilliseconds));
return img;
}

View File

@ -157,6 +157,23 @@ namespace Wox
UpdateResultView(results);
}
public void ShowContextMenu(PluginMetadata plugin, List<Result> results)
{
if (results != null && results.Count > 0)
{
results.ForEach(o =>
{
o.PluginDirectory = plugin.PluginDirectory;
o.PluginID = plugin.ID;
o.ContextMenu = null;
});
pnlContextMenu.Clear();
pnlContextMenu.AddResults(results);
pnlContextMenu.Visibility = Visibility.Visible;
pnlResult.Visibility = Visibility.Collapsed;
}
}
#endregion
public MainWindow()
@ -226,7 +243,7 @@ namespace Wox
void pnlResult_RightMouseClickEvent(Result result)
{
ShowContextMenu(result);
ShowContextMenuFromResult(result);
}
void MainWindow_Closing(object sender, CancelEventArgs e)
@ -368,6 +385,8 @@ namespace Wox
lastQuery = tbQuery.Text;
toolTip.IsOpen = false;
pnlResult.Dirty = true;
int searchDelay = GetSearchDelay(lastQuery);
Dispatcher.DelayInvoke("UpdateSearch",
o =>
{
@ -381,6 +400,7 @@ namespace Wox
}, TimeSpan.FromMilliseconds(100), null);
queryHasReturn = false;
Query query = new Query(lastQuery);
query.IsIntantQuery = searchDelay == 0;
FireBeforeWoxQueryEvent(query);
Query(query);
Dispatcher.DelayInvoke("ShowProgressbar", originQuery =>
@ -391,15 +411,18 @@ namespace Wox
}
}, TimeSpan.FromMilliseconds(150), tbQuery.Text);
FireAfterWoxQueryEvent(query);
}, TimeSpan.FromMilliseconds(GetSearchDelay(lastQuery)));
}, TimeSpan.FromMilliseconds(searchDelay));
}
private int GetSearchDelay(string query)
{
if (!string.IsNullOrEmpty(query) && PluginManager.IsInstantSearch(query))
{
DebugHelper.WriteLine("execute query without delay");
return 0;
}
DebugHelper.WriteLine("execute query with 200ms delay");
return 200;
}
@ -551,7 +574,7 @@ namespace Wox
}
else
{
ShowContextMenu(GetActiveResult());
ShowContextMenuFromResult(GetActiveResult());
}
}
break;
@ -609,7 +632,7 @@ namespace Wox
Result activeResult = GetActiveResult();
if (GlobalHotkey.Instance.CheckModifiers().ShiftPressed)
{
ShowContextMenu(activeResult);
ShowContextMenuFromResult(activeResult);
}
else
{
@ -740,7 +763,7 @@ namespace Wox
}
}
private void ShowContextMenu(Result result)
private void ShowContextMenuFromResult(Result result)
{
if (result.ContextMenu != null && result.ContextMenu.Count > 0)
{