diff --git a/Wox/Helper/ListBoxItems.cs b/Wox/Helper/ListBoxItems.cs index 103630d6e4..5d62edf11d 100644 --- a/Wox/Helper/ListBoxItems.cs +++ b/Wox/Helper/ListBoxItems.cs @@ -9,7 +9,7 @@ using Wox.Plugin; namespace Wox.Helper { class ListBoxItems : ObservableCollection - // todo implement custom moveItem,removeItem,insertItem + // todo implement custom moveItem,removeItem,insertItem for better performance { public void RemoveAll(Predicate predicate) { @@ -18,6 +18,7 @@ namespace Wox.Helper List itemsToRemove = Items.Where(x => predicate(x)).ToList(); if (itemsToRemove.Count > 0) { + itemsToRemove.ForEach(item => Items.Remove(item)); OnPropertyChanged(new PropertyChangedEventArgs("Count")); @@ -29,5 +30,38 @@ namespace Wox.Helper OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } } + + public void Update(List newItems) + { + int newCount = newItems.Count; + int oldCount = Items.Count; + int location = newCount > oldCount ? oldCount : newCount; + for (int i = 0; i < location; i++) + { + Result oldItem = Items[i]; + Result newItem = newItems[i]; + if (!Equals(oldItem, newItem)) + { + this[i] = newItem; + } + } + + if (newCount > oldCount) + { + for (int i = oldCount; i < newCount; i++) + { + Add(newItems[i]); + } + } + else + { + int removeIndex = newCount; + for (int i = newCount; i < oldCount; i++) + { + RemoveAt(removeIndex); + } + } + + } } } diff --git a/Wox/ResultPanel.xaml.cs b/Wox/ResultPanel.xaml.cs index 66f9a9fea9..24d5385c3b 100644 --- a/Wox/ResultPanel.xaml.cs +++ b/Wox/ResultPanel.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; @@ -21,7 +22,7 @@ namespace Wox public event Action LeftMouseClickEvent; public event Action RightMouseClickEvent; public event Action ItemDropEvent; - private readonly ListBoxItems _results; //todo, for better performance, override the default linear search + private readonly ListBoxItems _results; private readonly object _resultsUpdateLock = new object(); protected virtual void OnRightMouseClick(Result result) @@ -57,15 +58,16 @@ namespace Wox public void AddResults(List newResults, string resultId) { - var oldResults = _results.Where(r => r.PluginID == resultId).ToList(); - // intersection of A (old results) and B (new newResults) - var intersection = oldResults.Intersect(newResults).ToList(); lock (_resultsUpdateLock) { + var resultCopy = _results.ToList(); + var oldResults = resultCopy.Where(r => r.PluginID == resultId).ToList(); + // intersection of A (old results) and B (new newResults) + var intersection = oldResults.Intersect(newResults).ToList(); // remove result of relative complement of B in A foreach (var result in oldResults.Except(intersection)) { - _results.Remove(result); + resultCopy.Remove(result); } // update scores @@ -80,14 +82,16 @@ namespace Wox // update index for result in intersection of A and B foreach (var result in intersection) { - int oldIndex = _results.IndexOf(result); - int oldScore = _results[oldIndex].Score; + int oldIndex = resultCopy.IndexOf(result); + int oldScore = resultCopy[oldIndex].Score; if (result.Score != oldScore) { - int newIndex = InsertIndexOf(result.Score); + int newIndex = InsertIndexOf(result.Score, resultCopy); if (newIndex != oldIndex) { - _results.Move(oldIndex, newIndex); + var item = resultCopy[oldIndex]; + resultCopy.RemoveAt(oldIndex); + resultCopy.Insert(newIndex, item); } } } @@ -95,9 +99,13 @@ namespace Wox // insert result in relative complement of A in B foreach (var result in newResults.Except(intersection)) { - int newIndex = InsertIndexOf(result.Score); - _results.Insert(newIndex, result); + int newIndex = InsertIndexOf(result.Score, resultCopy); + resultCopy.Insert(newIndex, result); } + + // update UI in one run, so it can avoid UI flickering + _results.Update(resultCopy); + lbResults.Margin = lbResults.Items.Count > 0 ? new Thickness { Top = 8 } : new Thickness { Top = 0 }; SelectFirst(); } @@ -108,13 +116,13 @@ namespace Wox return TopMostRecordStorage.Instance.IsTopMost(result); } - private int InsertIndexOf(int newScore) + private int InsertIndexOf(int newScore, IList list) { int index = 0; - for (; index < lbResults.Items.Count; index++) + for (; index < list.Count; index++) { - Result result = lbResults.Items[index] as Result; - if (newScore > result?.Score) + var result = list[index]; + if (newScore > result.Score) { break; }