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
This commit is contained in:
bao-qian
2015-11-08 01:44:28 +00:00
parent 9627272b57
commit 2b27e84956
2 changed files with 58 additions and 16 deletions

View File

@@ -9,7 +9,7 @@ using Wox.Plugin;
namespace Wox.Helper namespace Wox.Helper
{ {
class ListBoxItems : ObservableCollection<Result> class ListBoxItems : ObservableCollection<Result>
// todo implement custom moveItem,removeItem,insertItem // todo implement custom moveItem,removeItem,insertItem for better performance
{ {
public void RemoveAll(Predicate<Result> predicate) public void RemoveAll(Predicate<Result> predicate)
{ {
@@ -18,6 +18,7 @@ namespace Wox.Helper
List<Result> itemsToRemove = Items.Where(x => predicate(x)).ToList(); List<Result> itemsToRemove = Items.Where(x => predicate(x)).ToList();
if (itemsToRemove.Count > 0) if (itemsToRemove.Count > 0)
{ {
itemsToRemove.ForEach(item => Items.Remove(item)); itemsToRemove.ForEach(item => Items.Remove(item));
OnPropertyChanged(new PropertyChangedEventArgs("Count")); OnPropertyChanged(new PropertyChangedEventArgs("Count"));
@@ -29,5 +30,38 @@ namespace Wox.Helper
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
} }
} }
public void Update(List<Result> 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);
}
}
}
} }
} }

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
@@ -21,7 +22,7 @@ namespace Wox
public event Action<Result> LeftMouseClickEvent; public event Action<Result> LeftMouseClickEvent;
public event Action<Result> RightMouseClickEvent; public event Action<Result> RightMouseClickEvent;
public event Action<Result, IDataObject, DragEventArgs> ItemDropEvent; public event Action<Result, IDataObject, DragEventArgs> ItemDropEvent;
private readonly ListBoxItems _results; //todo, for better performance, override the default linear search private readonly ListBoxItems _results;
private readonly object _resultsUpdateLock = new object(); private readonly object _resultsUpdateLock = new object();
protected virtual void OnRightMouseClick(Result result) protected virtual void OnRightMouseClick(Result result)
@@ -57,15 +58,16 @@ namespace Wox
public void AddResults(List<Result> newResults, string resultId) public void AddResults(List<Result> 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) 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 // remove result of relative complement of B in A
foreach (var result in oldResults.Except(intersection)) foreach (var result in oldResults.Except(intersection))
{ {
_results.Remove(result); resultCopy.Remove(result);
} }
// update scores // update scores
@@ -80,14 +82,16 @@ namespace Wox
// update index for result in intersection of A and B // update index for result in intersection of A and B
foreach (var result in intersection) foreach (var result in intersection)
{ {
int oldIndex = _results.IndexOf(result); int oldIndex = resultCopy.IndexOf(result);
int oldScore = _results[oldIndex].Score; int oldScore = resultCopy[oldIndex].Score;
if (result.Score != oldScore) if (result.Score != oldScore)
{ {
int newIndex = InsertIndexOf(result.Score); int newIndex = InsertIndexOf(result.Score, resultCopy);
if (newIndex != oldIndex) 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 // insert result in relative complement of A in B
foreach (var result in newResults.Except(intersection)) foreach (var result in newResults.Except(intersection))
{ {
int newIndex = InsertIndexOf(result.Score); int newIndex = InsertIndexOf(result.Score, resultCopy);
_results.Insert(newIndex, result); 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 }; lbResults.Margin = lbResults.Items.Count > 0 ? new Thickness { Top = 8 } : new Thickness { Top = 0 };
SelectFirst(); SelectFirst();
} }
@@ -108,13 +116,13 @@ namespace Wox
return TopMostRecordStorage.Instance.IsTopMost(result); return TopMostRecordStorage.Instance.IsTopMost(result);
} }
private int InsertIndexOf(int newScore) private int InsertIndexOf(int newScore, IList<Result> list)
{ {
int index = 0; int index = 0;
for (; index < lbResults.Items.Count; index++) for (; index < list.Count; index++)
{ {
Result result = lbResults.Items[index] as Result; var result = list[index];
if (newScore > result?.Score) if (newScore > result.Score)
{ {
break; break;
} }