diff --git a/Wox/HotkeyControl.xaml b/Wox/HotkeyControl.xaml index 6ea40d1cd3..b3052ff164 100644 --- a/Wox/HotkeyControl.xaml +++ b/Wox/HotkeyControl.xaml @@ -11,7 +11,7 @@ - + diff --git a/Wox/ImagePathConverter.cs b/Wox/ImagePathConverter.cs new file mode 100644 index 0000000000..41d7543704 --- /dev/null +++ b/Wox/ImagePathConverter.cs @@ -0,0 +1,55 @@ +using System; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Windows; +using System.Windows.Data; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace Wox +{ + public class ImagePathConverter : IMultiValueConverter + { + private static ImageSource GetIcon(string fileName) + { + Icon icon = Icon.ExtractAssociatedIcon(fileName); + return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon( + icon.Handle, + new Int32Rect(0, 0, icon.Width, icon.Height), + BitmapSizeOptions.FromEmptyOptions()); + } + + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + if (values[0] == null) return null; + + string path = values[0].ToString(); + string pluginDirectory = values[1].ToString(); + + string resolvedPath = string.Empty; + if (!string.IsNullOrEmpty(path) && path.Contains(":\\") && File.Exists(path)) + { + resolvedPath = path; + } + else if (!string.IsNullOrEmpty(path) && File.Exists(pluginDirectory + path)) + { + resolvedPath = pluginDirectory + path; + } + + if (resolvedPath.ToLower().EndsWith(".exe") || resolvedPath.ToLower().EndsWith(".lnk")) + { + return GetIcon(resolvedPath); + } + + if(!string.IsNullOrEmpty(path)) return new BitmapImage(new Uri(resolvedPath)); + + return null; + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 7be4a4f61d..df812bf2d9 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.ComponentModel; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; @@ -30,8 +30,9 @@ namespace Wox public partial class MainWindow { private static readonly object locker = new object(); - private readonly GloablHotkey globalHotkey = new GloablHotkey(); + private static readonly List waitShowResultList = new List(); + private readonly GloablHotkey globalHotkey = new GloablHotkey(); private readonly KeyboardSimulator keyboardSimulator = new KeyboardSimulator(new InputSimulator()); private readonly Storyboard progressBarStoryboard = new Storyboard(); private bool WinRStroked; @@ -43,7 +44,7 @@ namespace Wox InitializeComponent(); InitialTray(); - resultCtrl.resultItemChangedEvent += resultCtrl_resultItemChangedEvent; + ThreadPool.SetMaxThreads(30, 10); InitProgressbarAnimation(); try @@ -54,17 +55,14 @@ namespace Wox { SetTheme(CommonStorage.Instance.UserSetting.Theme = "Default"); } - - - Closing += MainWindow_Closing; } - public void SetHotkey(string hotkeyStr,EventHandler action) + public void SetHotkey(string hotkeyStr, EventHandler action) { - HotkeyModel hotkey = new HotkeyModel(hotkeyStr); + var hotkey = new HotkeyModel(hotkeyStr); try { - HotkeyManager.Current.AddOrReplace(hotkeyStr, hotkey.CharKey, hotkey.ModifierKeys,action); + HotkeyManager.Current.AddOrReplace(hotkeyStr, hotkey.CharKey, hotkey.ModifierKeys, action); } catch (Exception) { @@ -74,15 +72,19 @@ namespace Wox public void RemoveHotkey(string hotkeyStr) { - HotkeyManager.Current.Remove(hotkeyStr); + if (!string.IsNullOrEmpty(hotkeyStr)) + { + HotkeyManager.Current.Remove(hotkeyStr); + } } private void SetCustomPluginHotkey() { + if (CommonStorage.Instance.UserSetting.CustomPluginHotkeys == null) return; foreach (CustomPluginHotkey hotkey in CommonStorage.Instance.UserSetting.CustomPluginHotkeys) { CustomPluginHotkey hotkey1 = hotkey; - SetHotkey(hotkey.Hotkey,delegate + SetHotkey(hotkey.Hotkey, delegate { ShowApp(); ChangeQuery(hotkey1.ActionKeyword); @@ -103,18 +105,13 @@ namespace Wox e.Handled = true; } - private void MainWindow_Closing(object sender, CancelEventArgs e) - { - e.Cancel = true; - } - private void WakeupApp() { //After hide wox in the background for a long time. It will become very slow in the next show. //This is caused by the Virtual Mermory Page Mechanisam. So, our solution is execute some codes in every min //which may prevent sysetem uninstall memory from RAM to disk. - var t = new Timer(1000 * 60 * 5) { AutoReset = true, Enabled = true }; + var t = new Timer(1000*60*5) {AutoReset = true, Enabled = true}; t.Elapsed += (o, e) => Dispatcher.Invoke(new Action(() => { if (Visibility != Visibility.Visible) @@ -144,23 +141,16 @@ namespace Wox private void InitialTray() { - notifyIcon = new NotifyIcon { Text = "Wox", Icon = Properties.Resources.app, Visible = true }; + notifyIcon = new NotifyIcon {Text = "Wox", Icon = Properties.Resources.app, Visible = true}; notifyIcon.Click += (o, e) => ShowWox(); var open = new MenuItem("Open"); open.Click += (o, e) => ShowWox(); var exit = new MenuItem("Exit"); exit.Click += (o, e) => CloseApp(); - MenuItem[] childen = { open, exit }; + MenuItem[] childen = {open, exit}; notifyIcon.ContextMenu = new ContextMenu(childen); } - private void resultCtrl_resultItemChangedEvent() - { - resultCtrl.Margin = resultCtrl.GetCurrentResultCount() > 0 - ? new Thickness { Top = grid.Margin.Top } - : new Thickness { Top = 0 }; - } - private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e) { resultCtrl.Dirty = true; @@ -243,12 +233,12 @@ namespace Wox private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) { - Left = (SystemParameters.PrimaryScreenWidth - ActualWidth) / 2; - Top = (SystemParameters.PrimaryScreenHeight - ActualHeight) / 3; + Left = (SystemParameters.PrimaryScreenWidth - ActualWidth)/2; + Top = (SystemParameters.PrimaryScreenHeight - ActualHeight)/3; - SetHotkey(CommonStorage.Instance.UserSetting.Hotkey,OnHotkey); + SetHotkey(CommonStorage.Instance.UserSetting.Hotkey, OnHotkey); SetCustomPluginHotkey(); - WakeupApp(); + //WakeupApp(); Plugins.Init(); globalHotkey.hookedKeyboardCallback += KListener_hookedKeyboardCallback; @@ -259,13 +249,13 @@ namespace Wox if (CommonStorage.Instance.UserSetting.ReplaceWinR) { //todo:need refatoring. move those codes to CMD file or expose events - if (keyevent == KeyEvent.WM_KEYDOWN && vkcode == (int)Keys.R && state.WinPressed) + if (keyevent == KeyEvent.WM_KEYDOWN && vkcode == (int) Keys.R && state.WinPressed) { WinRStroked = true; Dispatcher.BeginInvoke(new Action(OnWinRPressed)); return false; } - if (keyevent == KeyEvent.WM_KEYUP && WinRStroked && vkcode == (int)Keys.LWin) + if (keyevent == KeyEvent.WM_KEYUP && WinRStroked && vkcode == (int) Keys.LWin) { WinRStroked = false; keyboardSimulator.ModifiedKeyStroke(VirtualKeyCode.LWIN, VirtualKeyCode.CONTROL); @@ -341,13 +331,21 @@ namespace Wox }); lock (locker) { - resultCtrl.Dispatcher.Invoke(new Action(() => - { - List l = - list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == tbQuery.Text).ToList(); - resultCtrl.AddResults(list); - })); + waitShowResultList.AddRange(list); } + Dispatcher.DelayInvoke("ShowResult", k => resultCtrl.Dispatcher.Invoke(new Action(() => + { + int t1 = Environment.TickCount; + + List l = + waitShowResultList.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == tbQuery.Text) + .ToList(); + waitShowResultList.Clear(); + + resultCtrl.AddResults(l); + + Debug.WriteLine("Total Time:" + (Environment.TickCount - t1) + " Count:" + l.Count); + })), TimeSpan.FromMilliseconds(50)); } } @@ -373,6 +371,7 @@ namespace Wox public void CloseApp() { notifyIcon.Visible = false; + Close(); Environment.Exit(0); } @@ -388,7 +387,7 @@ namespace Wox public void ShowMsg(string title, string subTitle, string iconPath) { - var m = new Msg { Owner = GetWindow(this) }; + var m = new Msg {Owner = GetWindow(this)}; m.Show(title, subTitle, iconPath); } diff --git a/Wox/ResultItem.xaml b/Wox/ResultItem.xaml deleted file mode 100644 index ea5b63db5b..0000000000 --- a/Wox/ResultItem.xaml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - Title - sub title - - - diff --git a/Wox/ResultItem.xaml.cs b/Wox/ResultItem.xaml.cs deleted file mode 100644 index e4bb0bf109..0000000000 --- a/Wox/ResultItem.xaml.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.ComponentModel; -using System.Drawing; -using System.IO; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using Wox.Annotations; -using Wox.Helper; -using Wox.Infrastructure; -using Wox.Plugin; -using Brush = System.Windows.Media.Brush; - -namespace Wox -{ - public partial class ResultItem : UserControl, INotifyPropertyChanged - { - private bool selected; - - public Result Result { get; private set; } - - public bool Selected - { - get - { - return selected; - } - set - { - selected = value; - OnPropertyChanged("Selected"); - } - } - - public ResultItem(Result result) - { - InitializeComponent(); - Result = result; - - tbTitle.Text = result.Title; - tbSubTitle.Text = result.SubTitle; - if (string.IsNullOrEmpty(result.SubTitle)) - { - SubTitleRowDefinition.Height = new GridLength(0); - } - string path = string.Empty; - if (!string.IsNullOrEmpty(result.IcoPath) && result.IcoPath.Contains(":\\") && File.Exists(result.IcoPath)) - { - path = result.IcoPath; - } - else if (!string.IsNullOrEmpty(result.IcoPath) && File.Exists(result.PluginDirectory + result.IcoPath)) - { - path = result.PluginDirectory + result.IcoPath; - } - - if (!string.IsNullOrEmpty(path)) - { - if (path.ToLower().EndsWith(".exe") || path.ToLower().EndsWith(".lnk")) - { - imgIco.Source = GetIcon(path); - } - else - { - imgIco.Source = new BitmapImage(new Uri(path)); - } - } - - AddHandler(MouseLeftButtonUpEvent, new RoutedEventHandler((o, e) => - { - if (Result.Action != null) - Result.Action(new ActionContext() - { - SpecialKeyState = new GloablHotkey().CheckModifiers() - }); - - CommonStorage.Instance.UserSelectedRecords.Add(result); - if (!result.DontHideWoxAfterSelect) - { - App.Window.HideApp(); - } - e.Handled = true; - })); - } - - private static ImageSource GetIcon(string fileName) - { - Icon icon = Icon.ExtractAssociatedIcon(fileName); - return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon( - icon.Handle, - new Int32Rect(0, 0, icon.Width, icon.Height), - BitmapSizeOptions.FromEmptyOptions()); - } - - public event PropertyChangedEventHandler PropertyChanged; - - [NotifyPropertyChangedInvocator] - protected virtual void OnPropertyChanged(string propertyName) - { - PropertyChangedEventHandler handler = PropertyChanged; - if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); - } - } -} diff --git a/Wox/ResultPanel.xaml b/Wox/ResultPanel.xaml index c5efe75d31..ebf6738755 100644 --- a/Wox/ResultPanel.xaml +++ b/Wox/ResultPanel.xaml @@ -3,9 +3,55 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:wox="clr-namespace:Wox" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Wox/ResultPanel.xaml.cs b/Wox/ResultPanel.xaml.cs index d7189847c3..1bf5004a3d 100644 --- a/Wox/ResultPanel.xaml.cs +++ b/Wox/ResultPanel.xaml.cs @@ -1,5 +1,6 @@ -using System.Collections.Generic; -using System.Linq; +using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Windows; using System.Windows.Controls; using Wox.Helper; @@ -12,70 +13,37 @@ namespace Wox { public bool Dirty { get; set; } - public delegate void ResultItemsChanged(); - - public event ResultItemsChanged resultItemChangedEvent; - - protected virtual void OnResultItemChangedEvent() - { - ResultItemsChanged handler = resultItemChangedEvent; - if (handler != null) handler(); - } - public void AddResults(List results) { - if (results.Count == 0) return; - if (Dirty) { Dirty = false; - pnlContainer.Children.Clear(); + lbResults.Items.Clear(); } - - for (int i = 0; i < results.Count; i++) + foreach (var result in results) { - Result result = results[i]; - if (!CheckExisted(result)) - { - ResultItem control = new ResultItem(result); - pnlContainer.Children.Insert(GetInsertLocation(result.Score), control); - } + int position = GetInsertLocation(result.Score); + lbResults.Items.Insert(position, result); } - + gridContainer.Margin = lbResults.Items.Count > 0 ? new Thickness { Top = 8 } : new Thickness { Top = 0 }; SelectFirst(); - pnlContainer.UpdateLayout(); - - double resultItemHeight = 0; - if (pnlContainer.Children.Count > 0) - { - var resultItem = pnlContainer.Children[0] as ResultItem; - if (resultItem != null) - resultItemHeight = resultItem.ActualHeight; - } - pnlContainer.Height = pnlContainer.Children.Count * resultItemHeight; - OnResultItemChangedEvent(); - } - - private bool CheckExisted(Result result) - { - return pnlContainer.Children.Cast().Any(child => child.Result.Equals(result)); } private int GetInsertLocation(int currentScore) { - int location = pnlContainer.Children.Count; - if (pnlContainer.Children.Count == 0) return 0; - if (currentScore > ((ResultItem)pnlContainer.Children[0]).Result.Score) return 0; + int location = lbResults.Items.Count; + if (lbResults.Items.Count == 0) return 0; + if (currentScore > ((Result)lbResults.Items[0]).Score) return 0; - for (int index = 1; index < pnlContainer.Children.Count; index++) + for (int index = 1; index < lbResults.Items.Count; index++) { - ResultItem next = pnlContainer.Children[index] as ResultItem; - ResultItem prev = pnlContainer.Children[index - 1] as ResultItem; + Result next = lbResults.Items[index] as Result; + Result prev = lbResults.Items[index - 1] as Result; if (next != null && prev != null) { - if ((currentScore >= next.Result.Score && currentScore <= prev.Result.Score)) + if ((currentScore >= next.Score && currentScore <= prev.Score)) { - if (currentScore == next.Result.Score) + if (currentScore == next.Score) { location = index + 1; } @@ -90,40 +58,10 @@ namespace Wox return location; } - public int GetCurrentResultCount() - { - return pnlContainer.Children.Count; - } - - public int GetCurrentSelectedResultIndex() - { - for (int i = 0; i < pnlContainer.Children.Count; i++) - { - var resultItemControl = pnlContainer.Children[i] as ResultItem; - if (resultItemControl != null && resultItemControl.Selected) - { - return i; - } - } - return -1; - } - - public void UnSelectAll() - { - for (int i = 0; i < pnlContainer.Children.Count; i++) - { - var resultItemControl = pnlContainer.Children[i] as ResultItem; - if (resultItemControl != null && resultItemControl.Selected) - { - resultItemControl.Selected = false; - } - } - } - public void SelectNext() { - int index = GetCurrentSelectedResultIndex(); - if (index == pnlContainer.Children.Count - 1) + int index = lbResults.SelectedIndex; + if (index == lbResults.Items.Count - 1) { index = -1; } @@ -132,95 +70,44 @@ namespace Wox public void SelectPrev() { - int index = GetCurrentSelectedResultIndex(); + int index = lbResults.SelectedIndex; if (index == 0) { - index = pnlContainer.Children.Count; + index = lbResults.Items.Count; } Select(index - 1); } - private void Select(int index) - { - if (pnlContainer.Children.Count > 0) - { - int oldIndex = GetCurrentSelectedResultIndex(); - - UnSelectAll(); - var resultItemControl = pnlContainer.Children[index] as ResultItem; - if (resultItemControl != null) - { - resultItemControl.Selected = true; - - double scrollPosition = 0; - Point newItemBottomPoint = resultItemControl.TranslatePoint(new Point(0, resultItemControl.ActualHeight), pnlContainer); - scrollPosition = newItemBottomPoint.Y; - if (index == 0) - { - sv.ScrollToTop(); - return; - } - if (index == pnlContainer.Children.Count - 1) - { - sv.ScrollToBottom(); - return; - } - - if (index < oldIndex) - { - //move up and old item is at the top of the scroll view - var scrollPostionY = sv.VerticalOffset - sv.VerticalOffset%resultItemControl.ActualHeight + - resultItemControl.ActualHeight; - if (newItemBottomPoint.Y - scrollPostionY == 0) - { - scrollPosition = sv.VerticalOffset - resultItemControl.ActualHeight; - } - else - { - return; - } - } - else - { - //move down and old item is at the bottom of scroll view - double scrollPostionY = (sv.ActualHeight + sv.VerticalOffset) - (sv.ActualHeight + sv.VerticalOffset)%resultItemControl.ActualHeight; - if (scrollPostionY == newItemBottomPoint.Y - resultItemControl.ActualHeight) - { - scrollPosition = newItemBottomPoint.Y - sv.ActualHeight; - } - else - { - return; - } - } - - sv.ScrollToVerticalOffset(scrollPosition); - } - } - } - - public void SelectFirst() + private void SelectFirst() { Select(0); } + private void Select(int index) + { + if (index >= 0 && index < lbResults.Items.Count) + { + lbResults.SelectedItem = lbResults.Items.GetItemAt(index); + } + } + public Result AcceptSelect() { - int index = GetCurrentSelectedResultIndex(); + int index = lbResults.SelectedIndex; if (index < 0) return null; - var resultItemControl = pnlContainer.Children[index] as ResultItem; - if (resultItemControl != null) + var result = lbResults.Items[index] as Result; + if (result != null) { - if (resultItemControl.Result.Action != null) + if (result.Action != null) { - resultItemControl.Result.Action(new ActionContext() + result.Action(new ActionContext() { SpecialKeyState = new GloablHotkey().CheckModifiers() }); } - return resultItemControl.Result; + return result; } return null; @@ -233,9 +120,16 @@ namespace Wox public void Clear() { - pnlContainer.Children.Clear(); - pnlContainer.Height = 0; - OnResultItemChangedEvent(); + lbResults.Items.Clear(); + gridContainer.Margin = new Thickness { Top = 0 }; + } + + private void lbResults_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (e.AddedItems.Count > 0) + { + lbResults.ScrollIntoView(e.AddedItems[0]); + } } } } \ No newline at end of file diff --git a/Wox/StringNullOrEmptyToVisibilityConverter.cs b/Wox/StringNullOrEmptyToVisibilityConverter.cs new file mode 100644 index 0000000000..8ed4b71c86 --- /dev/null +++ b/Wox/StringNullOrEmptyToVisibilityConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; +using System.Windows.Markup; + +namespace Wox +{ + public class StringNullOrEmptyToVisibilityConverter : MarkupExtension, IValueConverter + { + public override object ProvideValue(IServiceProvider serviceProvider) + { + return this; + } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return string.IsNullOrEmpty(value as string) ? Visibility.Collapsed : Visibility.Visible; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Wox/Themes/Default.xaml b/Wox/Themes/Default.xaml index 33e17dd46f..61447daf51 100644 --- a/Wox/Themes/Default.xaml +++ b/Wox/Themes/Default.xaml @@ -30,16 +30,35 @@ - - + + #4F6180 + + diff --git a/Wox/Themes/Light.xaml b/Wox/Themes/Light.xaml index 3fc48c9873..28c8f9f914 100644 --- a/Wox/Themes/Light.xaml +++ b/Wox/Themes/Light.xaml @@ -23,32 +23,42 @@ + - + + #543BFD + + @@ -123,4 +133,4 @@ - + \ No newline at end of file diff --git a/Wox/Wox.csproj b/Wox/Wox.csproj index 58aa7200ba..acc1016fc2 100644 --- a/Wox/Wox.csproj +++ b/Wox/Wox.csproj @@ -135,6 +135,7 @@ HotkeyControl.xaml + Msg.xaml @@ -147,12 +148,10 @@ ResultPanel.xaml - - ResultItem.xaml - SettingWindow.xaml + WebSearchSetting.xaml @@ -184,10 +183,6 @@ Designer MSBuild:Compile - - Designer - MSBuild:Compile - Designer MSBuild:Compile