Add IContextMenu interface & lazy load context menus

This commit is contained in:
qianlifeng 2015-02-07 23:49:46 +08:00
parent c24e216f26
commit bc7dce6026
10 changed files with 196 additions and 166 deletions

View File

@ -14,7 +14,7 @@ using Control = System.Windows.Controls.Control;
namespace Wox.Plugin.CMD namespace Wox.Plugin.CMD
{ {
public class CMD : IPlugin, ISettingProvider, IPluginI18n, IInstantQuery, IExclusiveQuery public class CMD : IPlugin, ISettingProvider, IPluginI18n, IInstantQuery, IExclusiveQuery,IContextMenu
{ {
private PluginInitContext context; private PluginInitContext context;
private bool WinRStroked; private bool WinRStroked;
@ -70,8 +70,7 @@ namespace Wox.Plugin.CMD
{ {
ExecuteCmd(m); ExecuteCmd(m);
return true; return true;
}, }
ContextMenu = GetContextMenus(m)
})); }));
} }
} }
@ -102,8 +101,7 @@ namespace Wox.Plugin.CMD
{ {
ExecuteCmd(m.Key); ExecuteCmd(m.Key);
return true; return true;
}, }
ContextMenu = GetContextMenus(m.Key)
}; };
return ret; return ret;
}).Where(o => o != null).Take(4); }).Where(o => o != null).Take(4);
@ -122,8 +120,7 @@ namespace Wox.Plugin.CMD
{ {
ExecuteCmd(cmd); ExecuteCmd(cmd);
return true; return true;
}, }
ContextMenu = GetContextMenus(cmd)
}; };
return result; return result;
@ -141,30 +138,11 @@ namespace Wox.Plugin.CMD
{ {
ExecuteCmd(m.Key); ExecuteCmd(m.Key);
return true; return true;
}, }
ContextMenu = GetContextMenus(m.Key)
}).Take(5); }).Take(5);
return history.ToList(); return history.ToList();
} }
private List<Result> GetContextMenus(string cmd)
{
return new List<Result>()
{
new Result()
{
Title = "Run As Administrator",
Action = c =>
{
context.API.HideApp();
ExecuteCmd(cmd, true);
return true;
},
IcoPath = "Images/cmd.png"
}
};
}
private void ExecuteCmd(string cmd, bool runAsAdministrator = false) private void ExecuteCmd(string cmd, bool runAsAdministrator = false)
{ {
if (context.API.ShellRun(cmd, runAsAdministrator)) if (context.API.ShellRun(cmd, runAsAdministrator))
@ -233,5 +211,23 @@ namespace Wox.Plugin.CMD
{ {
return query.Search.StartsWith(">"); return query.Search.StartsWith(">");
} }
public List<Result> LoadContextMenus(Result selectedResult)
{
return new List<Result>()
{
new Result()
{
Title = "Run As Administrator",
Action = c =>
{
context.API.HideApp();
ExecuteCmd(selectedResult.Title, true);
return true;
},
IcoPath = "Images/cmd.png"
}
};
}
} }
} }

View File

@ -6,10 +6,11 @@ using System.Linq;
using Wox.Infrastructure; using Wox.Infrastructure;
using System.Reflection; using System.Reflection;
using Wox.Plugin.Everything.Everything; using Wox.Plugin.Everything.Everything;
using Wox.Plugin.Features;
namespace Wox.Plugin.Everything namespace Wox.Plugin.Everything
{ {
public class Main : IPlugin, IPluginI18n public class Main : IPlugin, IPluginI18n,IContextMenu
{ {
PluginInitContext context; PluginInitContext context;
EverythingAPI api = new EverythingAPI(); EverythingAPI api = new EverythingAPI();
@ -24,7 +25,7 @@ namespace Wox.Plugin.Everything
var keyword = query.Search; var keyword = query.Search;
if (ContextMenuStorage.Instance.MaxSearchCount <= 0) if (ContextMenuStorage.Instance.MaxSearchCount <= 0)
{ {
ContextMenuStorage.Instance.MaxSearchCount = 100; ContextMenuStorage.Instance.MaxSearchCount = 50;
ContextMenuStorage.Instance.Save(); ContextMenuStorage.Instance.Save();
} }
@ -50,7 +51,7 @@ namespace Wox.Plugin.Everything
context.API.ShellRun(path); context.API.ShellRun(path);
return true; return true;
}; };
r.ContextMenu = GetContextMenu(s); r.ContextData = s;
results.Add(r); results.Add(r);
} }
} }
@ -110,43 +111,6 @@ namespace Wox.Plugin.Everything
[System.Runtime.InteropServices.DllImport("kernel32.dll")] [System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern int LoadLibrary(string name); private static extern int LoadLibrary(string name);
private List<Result> GetContextMenu(SearchResult record)
{
List<Result> contextMenus = new List<Result>();
List<ContextMenu> availableContextMenus = new List<ContextMenu>();
availableContextMenus.AddRange(GetDefaultContextMenu());
availableContextMenus.AddRange(ContextMenuStorage.Instance.ContextMenus);
if (record.Type == ResultType.File)
{
foreach (ContextMenu contextMenu in availableContextMenus)
{
contextMenus.Add(new Result()
{
Title = contextMenu.Name,
Action = _ =>
{
string argument = contextMenu.Argument.Replace("{path}", record.FullPath);
try
{
Process.Start(contextMenu.Command, argument);
}
catch
{
context.API.ShowMsg(string.Format(context.API.GetTranslation("wox_plugin_everything_canot_start"), record.FullPath), string.Empty, string.Empty);
return false;
}
return true;
},
IcoPath = contextMenu.ImagePath
});
}
}
return contextMenus;
}
private List<ContextMenu> GetDefaultContextMenu() private List<ContextMenu> GetDefaultContextMenu()
{ {
List<ContextMenu> defaultContextMenus = new List<ContextMenu>(); List<ContextMenu> defaultContextMenus = new List<ContextMenu>();
@ -221,5 +185,45 @@ namespace Wox.Plugin.Everything
{ {
return context.API.GetTranslation("wox_plugin_everything_plugin_description"); return context.API.GetTranslation("wox_plugin_everything_plugin_description");
} }
public List<Result> LoadContextMenus(Result selectedResult)
{
SearchResult record = selectedResult.ContextData as SearchResult;
List<Result> contextMenus = new List<Result>();
if(record == null) return contextMenus;
List<ContextMenu> availableContextMenus = new List<ContextMenu>();
availableContextMenus.AddRange(GetDefaultContextMenu());
availableContextMenus.AddRange(ContextMenuStorage.Instance.ContextMenus);
if (record.Type == ResultType.File)
{
foreach (ContextMenu contextMenu in availableContextMenus)
{
var menu = contextMenu;
contextMenus.Add(new Result()
{
Title = contextMenu.Name,
Action = _ =>
{
string argument = menu.Argument.Replace("{path}", record.FullPath);
try
{
Process.Start(menu.Command, argument);
}
catch
{
context.API.ShowMsg(string.Format(context.API.GetTranslation("wox_plugin_everything_canot_start"), record.FullPath), string.Empty, string.Empty);
return false;
}
return true;
},
IcoPath = contextMenu.ImagePath
});
}
}
return contextMenus;
}
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"ID":"D2D2C23B084D411DB66FE0C79D6C2A6E", "ID":"D2D2C23B084D411DB66FE0C79D6C2A6E",
"ActionKeyword":"f", "ActionKeyword":"*",
"Name":"Everything", "Name":"Everything",
"Description":"Search Everything", "Description":"Search Everything",
"Author":"qianlifeng,orzfly", "Author":"qianlifeng,orzfly",

View File

@ -9,10 +9,11 @@ using System.Windows;
using Wox.Infrastructure; using Wox.Infrastructure;
using Wox.Plugin.Program.ProgramSources; using Wox.Plugin.Program.ProgramSources;
using IWshRuntimeLibrary; using IWshRuntimeLibrary;
using Wox.Plugin.Features;
namespace Wox.Plugin.Program namespace Wox.Plugin.Program
{ {
public class Programs : ISettingProvider, IPlugin, IPluginI18n public class Programs : ISettingProvider, IPlugin, IPluginI18n, IContextMenu
{ {
private static object lockObject = new object(); private static object lockObject = new object();
private static List<Program> programs = new List<Program>(); private static List<Program> programs = new List<Program>();
@ -38,46 +39,12 @@ namespace Wox.Plugin.Program
SubTitle = c.ExecutePath, SubTitle = c.ExecutePath,
IcoPath = c.IcoPath, IcoPath = c.IcoPath,
Score = c.Score, Score = c.Score,
ContextData = c,
Action = (e) => Action = (e) =>
{ {
context.API.HideApp(); context.API.HideApp();
context.API.ShellRun(c.ExecutePath); context.API.ShellRun(c.ExecutePath);
return true; return true;
},
ContextMenu = new List<Result>()
{
new Result()
{
Title = context.API.GetTranslation("wox_plugin_program_run_as_administrator"),
Action = _ =>
{
context.API.HideApp();
context.API.ShellRun(c.ExecutePath,true);
return true;
},
IcoPath = "Images/cmd.png"
},
new Result()
{
Title = context.API.GetTranslation("wox_plugin_program_open_containing_folder"),
Action = _ =>
{
context.API.HideApp();
String Path=c.ExecutePath;
//check if shortcut
if (Path.EndsWith(".lnk"))
{
//get location of shortcut
Path = ResolveShortcut(Path);
}
//get parent folder
Path=System.IO.Directory.GetParent(Path).FullName;
//open the folder
context.API.ShellRun("explorer.exe "+Path,false);
return true;
},
IcoPath = "Images/folder.png"
}
} }
}).ToList(); }).ToList();
} }
@ -117,7 +84,7 @@ namespace Wox.Plugin.Program
void API_ResultItemDropEvent(Result result, IDataObject dropObject, DragEventArgs e) void API_ResultItemDropEvent(Result result, IDataObject dropObject, DragEventArgs e)
{ {
e.Handled = true; e.Handled = true;
} }
@ -232,5 +199,46 @@ namespace Wox.Plugin.Program
{ {
return context.API.GetTranslation("wox_plugin_program_plugin_description"); return context.API.GetTranslation("wox_plugin_program_plugin_description");
} }
public List<Result> LoadContextMenus(Result selectedResult)
{
Program p = selectedResult.ContextData as Program;
List<Result> contextMenus = new List<Result>()
{
new Result()
{
Title = context.API.GetTranslation("wox_plugin_program_run_as_administrator"),
Action = _ =>
{
context.API.HideApp();
context.API.ShellRun(p.ExecutePath, true);
return true;
},
IcoPath = "Images/cmd.png"
},
new Result()
{
Title = context.API.GetTranslation("wox_plugin_program_open_containing_folder"),
Action = _ =>
{
context.API.HideApp();
String Path = p.ExecutePath;
//check if shortcut
if (Path.EndsWith(".lnk"))
{
//get location of shortcut
Path = ResolveShortcut(Path);
}
//get parent folder
Path = Directory.GetParent(Path).FullName;
//open the folder
context.API.ShellRun("explorer.exe " + Path, false);
return true;
},
IcoPath = "Images/folder.png"
}
};
return contextMenus;
}
} }
} }

View File

@ -12,37 +12,18 @@ namespace Wox.Core
{ {
public static List<KeyValuePair<PluginPair, T>> LoadPluginInterfaces<T>() where T : class public static List<KeyValuePair<PluginPair, T>> LoadPluginInterfaces<T>() where T : class
{ {
List<PluginMetadata> CSharpPluginMetadatas = PluginManager.AllPlugins.Select(o => o.Metadata).Where(o => o.Language.ToUpper() == AllowedLanguage.CSharp.ToUpper()).ToList(); List<KeyValuePair<PluginPair, T>> results = new List<KeyValuePair<PluginPair, T>>();
List<KeyValuePair<PluginPair, T>> plugins = new List<KeyValuePair<PluginPair, T>>(); foreach (PluginPair pluginPair in PluginManager.AllPlugins)
foreach (PluginMetadata metadata in CSharpPluginMetadatas)
{ {
try //need to load types from AllPlugins
//PluginInitContext is only available in this instance
T type = pluginPair.Plugin as T;
if (type != null)
{ {
Assembly asm = Assembly.Load(AssemblyName.GetAssemblyName(metadata.ExecuteFilePath)); results.Add(new KeyValuePair<PluginPair, T>(pluginPair,type));
List<Type> types = asm.GetTypes().Where(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(typeof(T))).ToList();
if (types.Count == 0)
{
continue;
}
foreach (Type type in types)
{
plugins.Add(new KeyValuePair<PluginPair, T>(PluginManager.AllPlugins.First(o => o.Metadata.ID == metadata.ID),
Activator.CreateInstance(type) as T));
}
}
catch (System.Exception e)
{
Log.Error(string.Format("Couldn't load plugin {0}: {1}", metadata.Name, e.Message));
#if (DEBUG)
{
throw;
}
#endif
} }
} }
return results;
return plugins;
} }
public static List<T> LoadInterfacesFromAppDomain<T>() where T : class public static List<T> LoadInterfacesFromAppDomain<T>() where T : class

View File

@ -26,6 +26,7 @@ namespace Wox.Core.Plugin
private static List<PluginMetadata> pluginMetadatas; private static List<PluginMetadata> pluginMetadatas;
private static List<KeyValuePair<PluginPair, IInstantQuery>> instantSearches; private static List<KeyValuePair<PluginPair, IInstantQuery>> instantSearches;
private static List<KeyValuePair<PluginPair, IExclusiveQuery>> exclusiveSearchPlugins; private static List<KeyValuePair<PluginPair, IExclusiveQuery>> exclusiveSearchPlugins;
private static List<KeyValuePair<PluginPair, IContextMenu>> contextMenuPlugins;
public static String DebuggerMode { get; private set; } public static String DebuggerMode { get; private set; }
public static IPublicAPI API { get; private set; } public static IPublicAPI API { get; private set; }
@ -267,5 +268,34 @@ namespace Wox.Core.Plugin
{ {
return GetExclusivePlugin(query) != null || GetActionKeywordPlugin(query) != null; return GetExclusivePlugin(query) != null || GetActionKeywordPlugin(query) != null;
} }
public static List<Result> GetPluginContextMenus(Result result)
{
List<Result> contextContextMenus = new List<Result>();
if (contextMenuPlugins == null)
{
contextMenuPlugins = AssemblyHelper.LoadPluginInterfaces<IContextMenu>();
}
var contextMenuPlugin = contextMenuPlugins.FirstOrDefault(o => o.Key.Metadata.ID == result.PluginID);
if (contextMenuPlugin.Value != null)
{
try
{
return contextMenuPlugin.Value.LoadContextMenus(result);
}
catch (System.Exception e)
{
Log.Error(string.Format("Couldn't load plugin context menus {0}: {1}", contextMenuPlugin.Key.Metadata.Name, e.Message));
#if (DEBUG)
{
throw;
}
#endif
}
}
return contextContextMenus;
}
} }
} }

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Wox.Plugin.Features
{
public interface IContextMenu
{
List<Result> LoadContextMenus(Result selectedResult);
}
}

View File

@ -68,6 +68,7 @@ namespace Wox.Plugin
this.SubTitle = SubTitle; this.SubTitle = SubTitle;
} }
[Obsolete("Use IContextMenu instead")]
/// <summary> /// <summary>
/// Context menus associate with this result /// Context menus associate with this result
/// </summary> /// </summary>

View File

@ -46,6 +46,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="AllowedLanguage.cs" /> <Compile Include="AllowedLanguage.cs" />
<Compile Include="EventHandler.cs" /> <Compile Include="EventHandler.cs" />
<Compile Include="Features\IContextMenu.cs" />
<Compile Include="Features\IExclusiveQuery.cs" /> <Compile Include="Features\IExclusiveQuery.cs" />
<Compile Include="Features\IInstantQuery.cs" /> <Compile Include="Features\IInstantQuery.cs" />
<Compile Include="IHttpProxy.cs" /> <Compile Include="IHttpProxy.cs" />

View File

@ -155,14 +155,6 @@ namespace Wox
o.PluginDirectory = plugin.PluginDirectory; o.PluginDirectory = plugin.PluginDirectory;
o.PluginID = plugin.ID; o.PluginID = plugin.ID;
o.OriginQuery = query; o.OriginQuery = query;
if (o.ContextMenu != null)
{
o.ContextMenu.ForEach(t =>
{
t.PluginDirectory = plugin.PluginDirectory;
t.PluginID = plugin.ID;
});
}
}); });
UpdateResultView(results); UpdateResultView(results);
} }
@ -253,7 +245,7 @@ namespace Wox
void pnlResult_RightMouseClickEvent(Result result) void pnlResult_RightMouseClickEvent(Result result)
{ {
ShowContextMenuFromResult(result); ShowContextMenu(result);
} }
void MainWindow_Closing(object sender, CancelEventArgs e) void MainWindow_Closing(object sender, CancelEventArgs e)
@ -401,7 +393,7 @@ namespace Wox
List<Result> filterResults = new List<Result>(); List<Result> filterResults = new List<Result>();
foreach (Result contextMenu in CurrentContextMenus) foreach (Result contextMenu in CurrentContextMenus)
{ {
if (StringMatcher.IsMatch(contextMenu.Title, query) if (StringMatcher.IsMatch(contextMenu.Title, query)
|| StringMatcher.IsMatch(contextMenu.SubTitle, query)) || StringMatcher.IsMatch(contextMenu.SubTitle, query))
{ {
filterResults.Add(contextMenu); filterResults.Add(contextMenu);
@ -528,7 +520,10 @@ namespace Wox
private void HideWox() private void HideWox()
{ {
BackToResultMode(); if (IsInContextMenuMode)
{
BackToResultMode();
}
Hide(); Hide();
} }
@ -615,7 +610,7 @@ namespace Wox
} }
else else
{ {
ShowContextMenuFromResult(GetActiveResult()); ShowContextMenu(GetActiveResult());
} }
} }
break; break;
@ -673,7 +668,7 @@ namespace Wox
Result activeResult = GetActiveResult(); Result activeResult = GetActiveResult();
if (GlobalHotkey.Instance.CheckModifiers().ShiftPressed) if (GlobalHotkey.Instance.CheckModifiers().ShiftPressed)
{ {
ShowContextMenuFromResult(activeResult); ShowContextMenu(activeResult);
} }
else else
{ {
@ -795,11 +790,6 @@ namespace Wox
list.ForEach(o => list.ForEach(o =>
{ {
o.Score += UserSelectedRecordStorage.Instance.GetSelectedCount(o) * 5; o.Score += UserSelectedRecordStorage.Instance.GetSelectedCount(o) * 5;
if (o.ContextMenu == null)
{
o.ContextMenu = new List<Result>();
}
HanleTopMost(o);
}); });
List<Result> l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == lastQuery).ToList(); List<Result> l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == lastQuery).ToList();
Dispatcher.Invoke(new Action(() => Dispatcher.Invoke(new Action(() =>
@ -809,11 +799,11 @@ namespace Wox
} }
} }
private void HanleTopMost(Result result) private Result GetTopMostContextMenu(Result result)
{ {
if (TopMostRecordStorage.Instance.IsTopMost(result)) if (TopMostRecordStorage.Instance.IsTopMost(result))
{ {
result.ContextMenu.Add(new Result(GetTranslation("cancelTopMostInThisQuery"), "Images\\down.png") return new Result(GetTranslation("cancelTopMostInThisQuery"), "Images\\down.png")
{ {
PluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), PluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
Action = _ => Action = _ =>
@ -822,11 +812,11 @@ namespace Wox
ShowMsg("Succeed", "", ""); ShowMsg("Succeed", "", "");
return false; return false;
} }
}); };
} }
else else
{ {
result.ContextMenu.Add(new Result(GetTranslation("setAsTopMostInThisQuery"), "Images\\up.png") return new Result(GetTranslation("setAsTopMostInThisQuery"), "Images\\up.png")
{ {
PluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), PluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
Action = _ => Action = _ =>
@ -835,22 +825,29 @@ namespace Wox
ShowMsg("Succeed", "", ""); ShowMsg("Succeed", "", "");
return false; return false;
} }
}); };
} }
} }
private void ShowContextMenuFromResult(Result result) private void ShowContextMenu(Result result)
{ {
if (result.ContextMenu != null && result.ContextMenu.Count > 0) List<Result> results = PluginManager.GetPluginContextMenus(result);
results.ForEach(o =>
{ {
textBeforeEnterContextMenuMode = tbQuery.Text; o.PluginDirectory = PluginManager.GetPlugin(result.PluginID).Metadata.PluginDirectory;
ChangeQueryText(""); o.PluginID = result.PluginID;
pnlContextMenu.Clear(); o.OriginQuery = result.OriginQuery;
pnlContextMenu.AddResults(result.ContextMenu); });
CurrentContextMenus = result.ContextMenu;
pnlContextMenu.Visibility = Visibility.Visible; results.Add(GetTopMostContextMenu(result));
pnlResult.Visibility = Visibility.Collapsed;
} textBeforeEnterContextMenuMode = tbQuery.Text;
ChangeQueryText("");
pnlContextMenu.Clear();
pnlContextMenu.AddResults(results);
CurrentContextMenus = results;
pnlContextMenu.Visibility = Visibility.Visible;
pnlResult.Visibility = Visibility.Collapsed;
} }
public bool ShellRun(string cmd, bool runAsAdministrator = false) public bool ShellRun(string cmd, bool runAsAdministrator = false)