From 2b27e84956173fc33f2f0c2ebe510fd9feb20e2e Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sun, 8 Nov 2015 01:44:28 +0000 Subject: [PATCH] Enhance result panel update The last commit f132cb54baa000a245feb5da87149960f6dbd9f5 only fix UI flickering for different icon. This commit also fix the commit for same icon. e.g. in web search plugin, although the title is different, but the icon is not changes. part of #350 --- Wox/Helper/ListBoxItems.cs | 36 +++++++++++++++++++++++++++++++++++- Wox/ResultPanel.xaml.cs | 38 +++++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 16 deletions(-) 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; }