structure change

This commit is contained in:
qianlifeng
2014-01-03 23:52:36 +08:00
parent 1eb3f449e2
commit dc51bc39ab
27 changed files with 289 additions and 257 deletions

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WinAlfred.Helper;
using WinAlfred.Plugin;
namespace WinAlfred.Commands
{
public class Command
{
private PluginCommand pluginCmd;
private SystemCommand systemCmd;
public Command(MainWindow window)
{
pluginCmd = new PluginCommand(window);
systemCmd = new SystemCommand(window);
}
public void DispatchCommand(Query query)
{
systemCmd.Dispatch(query);
pluginCmd.Dispatch(query);
}
}
}

View File

@@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WinAlfred.Helper;
using WinAlfred.Plugin;
namespace WinAlfred.Commands
{
public class CommandDispatcher
{
private PluginCommand pluginCmd = new PluginCommand();
private SystemCommand systemCmd = new SystemCommand();
//public delegate void resultUpdateDelegate(List<Result> results);
//public event resultUpdateDelegate OnResultUpdateEvent;
//protected virtual void OnOnResultUpdateEvent(List<Result> list)
//{
// resultUpdateDelegate handler = OnResultUpdateEvent;
// if (handler != null) handler(list);
//}
public void DispatchCommand(Query query)
{
systemCmd.Dispatch(query);
pluginCmd.Dispatch(query);
}
}
}

View File

@@ -2,44 +2,54 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using WinAlfred.Helper;
using WinAlfred.Plugin;
using WinAlfred.PluginLoader;
namespace WinAlfred.Commands
{
public class PluginCommand
public class PluginCommand : BaseCommand
{
public void Dispatch(Query q)
public PluginCommand(MainWindow mainWindow)
: base(mainWindow)
{
//ThreadPool.QueueUserWorkItem(state =>
//{
}
public override void Dispatch(Query q)
{
foreach (PluginPair pair in Plugins.AllPlugins)
{
if (pair.Metadata.ActionKeyword == q.ActionName)
{
try
PluginPair pair1 = pair;
ThreadPool.QueueUserWorkItem(state =>
{
pair.Plugin.Query(q).ForEach(o => o.PluginDirectory = pair.Metadata.PluginDirecotry);
}
catch (Exception queryException)
{
Log.Error(string.Format("Plugin {0} query failed: {1}", pair.Metadata.Name,
queryException.Message));
#if (DEBUG)
try
{
throw;
List<Result> r = pair1.Plugin.Query(q);
r.ForEach(o =>
{
o.PluginDirectory = pair1.Metadata.PluginDirecotry;
o.OriginQuery = q;
});
UpdateResultView(r);
}
catch (Exception queryException)
{
Log.Error(string.Format("Plugin {0} query failed: {1}", pair1.Metadata.Name,
queryException.Message));
#if (DEBUG)
{
throw;
}
#endif
}
}
});
}
}
resultCtrl.Dispatcher.Invoke(new Action(() =>
{
resultCtrl.AddResults(results.OrderByDescending(o => o.Score).ToList());
resultCtrl.SelectFirst();
}));
//});
}
}
}

View File

@@ -2,15 +2,38 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using WinAlfred.Plugin;
using WinAlfred.PluginLoader;
namespace WinAlfred.Commands
{
public class SystemCommand
public class SystemCommand : BaseCommand
{
public void Dispatch(Query query)
private List<PluginPair> systemPlugins;
public SystemCommand(MainWindow window)
: base(window)
{
systemPlugins = Plugins.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System).ToList();
}
public override void Dispatch(Query query)
{
foreach (PluginPair pair in systemPlugins)
{
PluginPair pair1 = pair;
ThreadPool.QueueUserWorkItem(state =>
{
List<Result> results = pair1.Plugin.Query(query);
foreach (Result result in results)
{
result.PluginDirectory = pair1.Metadata.PluginDirecotry;
result.OriginQuery = query;
}
UpdateResultView(results);
});
}
}
}
}

BIN
WinAlfred/Images/lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -13,6 +13,7 @@ using WinAlfred.Helper;
using WinAlfred.Plugin;
using WinAlfred.PluginLoader;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using Timer = System.Threading.Timer;
namespace WinAlfred
{
@@ -21,11 +22,12 @@ namespace WinAlfred
private KeyboardHook hook = new KeyboardHook();
private List<Result> results = new List<Result>();
private NotifyIcon notifyIcon = null;
private CommandDispatcher cmdDispatcher = new CommandDispatcher();
private Command cmdDispatcher;
public MainWindow()
{
InitializeComponent();
hook.KeyPressed += OnHotKey;
hook.RegisterHotKey(XModifierKeys.Alt, Keys.Space);
resultCtrl.resultItemChangedEvent += resultCtrl_resultItemChangedEvent;
@@ -51,7 +53,12 @@ namespace WinAlfred
private void resultCtrl_resultItemChangedEvent()
{
Height = resultCtrl.pnlContainer.ActualHeight + tbQuery.Height + tbQuery.Margin.Top + tbQuery.Margin.Bottom;
resultCtrl.Margin = results.Count > 0 ? new Thickness { Bottom = 10, Left = 10, Right = 10 } : new Thickness { Bottom = 0, Left = 10, Right = 10 };
resultCtrl.Margin = resultCtrl.GetCurrentResultCount() > 0 ? new Thickness { Bottom = 10, Left = 10, Right = 10 } : new Thickness { Bottom = 0, Left = 10, Right = 10 };
if (resultCtrl.GetCurrentResultCount() == 1)
{
resultCtrl.SelectFirst();
}
}
private void OnHotKey(object sender, KeyPressedEventArgs e)
@@ -68,6 +75,19 @@ namespace WinAlfred
private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e)
{
resultCtrl.Dirty = true;
//auto clear results after 50ms if there are any results returned by plugins
//why we do this? because if we clear resulsts in the start of the text changed event
//we will see the splash. The more closer that clear and addResult method, the less splash we will see.
new Timer(o =>
{
if (resultCtrl.Dirty)
{
resultCtrl.Dispatcher.Invoke(new Action(() => resultCtrl.Clear()));
}
}, null, TimeSpan.FromMilliseconds(50),TimeSpan.FromMilliseconds(-1));
if (string.IsNullOrEmpty(tbQuery.Text)) return;
var q = new Query(tbQuery.Text);
cmdDispatcher.DispatchCommand(q);
}
@@ -77,7 +97,7 @@ namespace WinAlfred
Hide();
}
private void ShowWinAlfred()
public void ShowWinAlfred()
{
tbQuery.SelectAll();
Show();
@@ -87,7 +107,8 @@ namespace WinAlfred
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
Plugins.Init();
Plugins.Init(this);
cmdDispatcher = new Command(this);
ShowWinAlfred();
InitialTray();
}
@@ -118,5 +139,14 @@ namespace WinAlfred
break;
}
}
public void OnUpdateResultView(List<Result> list)
{
resultCtrl.Dispatcher.Invoke(new Action(() =>
{
List<Result> l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == tbQuery.Text).OrderByDescending(o => o.Score).ToList();
resultCtrl.AddResults(l);
}));
}
}
}

View File

@@ -30,25 +30,18 @@ namespace WinAlfred.PluginLoader
private static void ParseSystemPlugins()
{
try
{
Assembly asm = Assembly.GetAssembly(typeof (CMD));
List<Type> types = asm.GetTypes().Where(o => o.GetInterfaces().Contains(typeof(ISystemPlugin))).ToList();
foreach (Type type in types)
{
ISystemPlugin sysPlugin = Activator.CreateInstance(types[0]) as ISystemPlugin;
PluginMetadata metadata = new PluginMetadata();
}
}
catch (Exception e)
{
Log.Error(string.Format("Cound't load system plugin: {0}", e.Message));
#if (DEBUG)
{
throw;
}
#endif
}
PluginMetadata metadata = new PluginMetadata();
metadata.Name = "System Plugins";
metadata.Author = "System";
metadata.Description = "system plugins collection";
metadata.Language = AllowedLanguage.CSharp;
metadata.Version = "1.0";
metadata.PluginType = PluginType.System;
metadata.ActionKeyword = "*";
metadata.ExecuteFileName = "WinAlfred.Plugin.System.dll";
metadata.ExecuteFilePath = AppDomain.CurrentDomain.BaseDirectory + metadata.ExecuteFileName;
metadata.PluginDirecotry = AppDomain.CurrentDomain.BaseDirectory;
pluginMetadatas.Add(metadata);
}
private static void ParseThirdPartyPlugins()

View File

@@ -5,6 +5,7 @@ using System.Reflection;
using System.Threading;
using WinAlfred.Helper;
using WinAlfred.Plugin;
using WinAlfred.Plugin.System;
namespace WinAlfred.PluginLoader
{
@@ -20,28 +21,23 @@ namespace WinAlfred.PluginLoader
try
{
Assembly asm = Assembly.LoadFile(metadata.ExecuteFilePath);
List<Type> types = asm.GetTypes().Where(o => o.GetInterfaces().Contains(typeof (IPlugin))).ToList();
List<Type> types = asm.GetTypes().Where(o => o.IsClass && o.GetInterfaces().Contains(typeof(IPlugin)) || o.GetInterfaces().Contains(typeof(ISystemPlugin))).ToList();
if (types.Count == 0)
{
Log.Error(string.Format("Cound't load plugin {0}: didn't find the class who implement IPlugin",
metadata.Name));
continue;
}
if (types.Count > 1)
{
Log.Error(
string.Format(
"Cound't load plugin {0}: find more than one class who implement IPlugin, there should only one class implement IPlugin",
metadata.Name));
continue;
}
PluginPair pair = new PluginPair()
foreach (Type type in types)
{
Plugin = Activator.CreateInstance(types[0]) as IPlugin,
Metadata = metadata
};
plugins.Add(pair);
PluginPair pair = new PluginPair()
{
Plugin = Activator.CreateInstance(type) as IPlugin,
Metadata = metadata
};
plugins.Add(pair);
}
}
catch (Exception e)
{
@@ -61,10 +57,7 @@ namespace WinAlfred.PluginLoader
private void InitPlugin(List<PluginPair> plugins)
{
foreach (IPlugin plugin in plugins.Select(pluginPair => pluginPair.Plugin))
{
new Thread(plugin.Init).Start();
}
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using WinAlfred.Plugin;
namespace WinAlfred.PluginLoader
@@ -10,11 +11,24 @@ namespace WinAlfred.PluginLoader
{
private static List<PluginPair> plugins = new List<PluginPair>();
public static void Init()
public static void Init(MainWindow window)
{
plugins.Clear();
plugins.AddRange(new PythonPluginLoader().LoadPlugin());
plugins.AddRange(new CSharpPluginLoader().LoadPlugin());
foreach (IPlugin plugin in plugins.Select(pluginPair => pluginPair.Plugin))
{
IPlugin plugin1 = plugin;
ThreadPool.QueueUserWorkItem(o => plugin1.Init(new PluginInitContext()
{
Plugins = plugins,
ChangeQuery = s =>
{
window.tbQuery.Text = s;
window.ShowWinAlfred();
}
}));
}
}
public static List<PluginPair> AllPlugins

View File

@@ -22,10 +22,6 @@ namespace WinAlfred.PluginLoader
plugins.Add(pair);
}
foreach (IPlugin plugin in plugins.Select(pluginPair => pluginPair.Plugin))
{
new Thread(plugin.Init).Start();
}
return plugins;
}
}

View File

@@ -55,7 +55,7 @@ namespace WinAlfred.PluginLoader
}
public void Init()
public void Init(PluginInitContext context)
{
InitPythonEnv();
}

View File

@@ -21,7 +21,7 @@
<TextBlock x:Name="tbTitle" FontSize="16" Foreground="#37392c" FontWeight="Medium">Title</TextBlock>
<TextBlock Grid.Row="1" Foreground="#8e94a4" x:Name="tbSubTitle">sdfdsf</TextBlock>
</Grid>
<DockPanel Grid.Column="2" >
<DockPanel Grid.Column="2" Visibility="Hidden">
<Image Source="Images\ctrl.png" VerticalAlignment="Center"/>
<TextBlock x:Name="tbIndex" FontSize="16" Foreground="#5c1f87" Margin="0 5 0 0" Text="1" VerticalAlignment="Center" HorizontalAlignment="Left" />
</DockPanel>

View File

@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
@@ -39,7 +40,7 @@ namespace WinAlfred
tbTitle.Text = result.Title;
tbSubTitle.Text = result.SubTitle;
if (!string.IsNullOrEmpty(result.IcoPath))
if (!string.IsNullOrEmpty(result.IcoPath) && File.Exists(result.PluginDirectory + result.IcoPath))
{
imgIco.Source = new BitmapImage(new Uri(result.PluginDirectory + result.IcoPath));
}

View File

@@ -7,6 +7,8 @@ namespace WinAlfred
{
public partial class ResultPanel : UserControl
{
public bool Dirty { get; set; }
public delegate void ResultItemsChanged();
public event ResultItemsChanged resultItemChangedEvent;
@@ -19,7 +21,14 @@ namespace WinAlfred
public void AddResults(List<Result> results)
{
pnlContainer.Children.Clear();
if (results.Count == 0) return;
if (Dirty)
{
Dirty = false;
pnlContainer.Children.Clear();
}
for (int i = 0; i < results.Count; i++)
{
Result result = results[i];
@@ -41,6 +50,11 @@ namespace WinAlfred
OnResultItemChangedEvent();
}
public int GetCurrentResultCount()
{
return pnlContainer.Children.Count;
}
private int GetCurrentSelectedResultIndex()
{
for (int i = 0; i < pnlContainer.Children.Count; i++)
@@ -114,7 +128,7 @@ namespace WinAlfred
if (index < oldIndex)
{
//move up and old item is at the top of the scroll view
if ( newItemBottomPoint.Y - sv.VerticalOffset == 0)
if (newItemBottomPoint.Y - sv.VerticalOffset == 0)
{
scrollPosition = sv.VerticalOffset - resultItemControl.ActualHeight;
}
@@ -160,5 +174,12 @@ namespace WinAlfred
{
InitializeComponent();
}
public void Clear()
{
pnlContainer.Children.Clear();
pnlContainer.Height = 0;
OnResultItemChangedEvent();
}
}
}

View File

@@ -64,15 +64,16 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Commands\CommandDispatcher.cs" />
<Compile Include="Commands\BaseCommand.cs" />
<Compile Include="Commands\Command.cs" />
<Compile Include="Commands\PluginCommand.cs" />
<Compile Include="Commands\SystemCommand.cs" />
<Compile Include="Helper\IniParser.cs" />
<Compile Include="Helper\KeyboardHook.cs" />
<Compile Include="Helper\Log.cs" />
<Compile Include="Helper\WinAlfredException.cs" />
<Compile Include="PluginLoader\BasePluginLoader.cs" />
<Compile Include="PluginLoader\CSharpPluginLoader.cs" />
<Compile Include="Helper\IniParser.cs" />
<Compile Include="PluginLoader\Plugins.cs" />
<Compile Include="PluginLoader\PythonPluginLoader.cs" />
<Compile Include="PluginLoader\PythonPluginWrapper.cs" />
@@ -158,6 +159,9 @@
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<PropertyGroup>
<PostBuildEvent>xcopy /Y $(ProjectDir)Images\*.* $(SolutionDir)WinAlfred\bin\Debug\Images\</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">