From 4736921d056260407478e6692fed4d69ff98412e Mon Sep 17 00:00:00 2001 From: qianlifeng Date: Wed, 19 Feb 2014 22:50:15 +0800 Subject: [PATCH] Replace ResultItem usercontrol with listbox to improve ui performance --- Wox/ImagePathConverter.cs | 53 +++++++++++ Wox/MainWindow.xaml.cs | 8 +- Wox/ResultPanel.xaml | 46 ++++++++- Wox/ResultPanel.xaml.cs | 194 +++++++++----------------------------- Wox/Wox.csproj | 1 + 5 files changed, 142 insertions(+), 160 deletions(-) create mode 100644 Wox/ImagePathConverter.cs diff --git a/Wox/ImagePathConverter.cs b/Wox/ImagePathConverter.cs new file mode 100644 index 0000000000..8f988d8a56 --- /dev/null +++ b/Wox/ImagePathConverter.cs @@ -0,0 +1,53 @@ +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) + { + 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); + } + else + { + return new BitmapImage(new Uri(resolvedPath)); + } + } + + 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 6ea5410519..bd3702c066 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -40,7 +40,6 @@ namespace Wox InitialTray(); hook.KeyPressed += OnHotKey; hook.RegisterHotKey(XModifierKeys.Alt, Keys.Space); - resultCtrl.resultItemChangedEvent += resultCtrl_resultItemChangedEvent; ThreadPool.SetMaxThreads(30, 10); InitProgressbarAnimation(); try @@ -106,11 +105,6 @@ namespace Wox notifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu(childen); } - private void resultCtrl_resultItemChangedEvent() - { - resultCtrl.Margin = resultCtrl.GetCurrentResultCount() > 0 ? new Thickness { Top = grid.Margin.Top } : new Thickness { Top = 0 }; - } - private void OnHotKey(object sender, KeyPressedEventArgs e) { if (!IsVisible) @@ -301,8 +295,10 @@ namespace Wox }); resultCtrl.Dispatcher.Invoke(new Action(() => { + var t1 = Environment.TickCount; List l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == tbQuery.Text).ToList(); resultCtrl.AddResults(l); + Debug.WriteLine("Time:" + (Environment.TickCount - t1) + " Count:" + l.Count); })); } } diff --git a/Wox/ResultPanel.xaml b/Wox/ResultPanel.xaml index c5efe75d31..42806e17d4 100644 --- a/Wox/ResultPanel.xaml +++ b/Wox/ResultPanel.xaml @@ -3,9 +3,49 @@ 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 118f8923e8..10896ccf7f 100644 --- a/Wox/ResultPanel.xaml.cs +++ b/Wox/ResultPanel.xaml.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; -using System.Linq; -using System.Windows; +using System.Diagnostics; using System.Windows.Controls; using Wox.Helper; using Wox.Plugin; +using Point = System.Windows.Point; namespace Wox { @@ -11,70 +11,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); } - + lbResults.UpdateLayout(); 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; } @@ -89,40 +56,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; } @@ -131,95 +68,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 KeyboardListener().CheckModifiers() }); } - return resultItemControl.Result; + return result; } return null; @@ -232,9 +118,15 @@ namespace Wox public void Clear() { - pnlContainer.Children.Clear(); - pnlContainer.Height = 0; - OnResultItemChangedEvent(); + lbResults.Items.Clear(); + } + + 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/Wox.csproj b/Wox/Wox.csproj index 25fc11a8de..0580c2c3b2 100644 --- a/Wox/Wox.csproj +++ b/Wox/Wox.csproj @@ -125,6 +125,7 @@ + Msg.xaml