Index: chrome/browser/ui/app_list/search/mixer.cc |
diff --git a/chrome/browser/ui/app_list/search/mixer.cc b/chrome/browser/ui/app_list/search/mixer.cc |
index 6a737713492183c446f450610d0811731f52e34c..8e3801cce5653b2aed21d35a748552d11dbdd712 100644 |
--- a/chrome/browser/ui/app_list/search/mixer.cc |
+++ b/chrome/browser/ui/app_list/search/mixer.cc |
@@ -66,30 +66,63 @@ void RemoveDuplicates(SortedResults* results) { |
results->swap(final); |
} |
-// Publishes the given |results| to |ui_results|. Reuse existing ones to avoid |
-// flickering. |
-void Publish(const SortedResults& results, |
+// Publishes the given |new_results| to |ui_results|. Reuse existing ones to |
Matt Giuca
2014/07/04 08:21:21
I'm a little skeptical of the name |new_results|,
calamity
2014/07/08 09:47:20
Done. Also changed the second sentence to better d
|
+// avoid flickering. |
+void Publish(const SortedResults& new_results, |
Matt Giuca
2014/07/04 08:21:21
I think there should be unit tests for this functi
calamity
2014/07/08 09:47:21
Done.
|
AppListModel::SearchResults* ui_results) { |
Matt Giuca
2014/07/04 08:21:22
It might be nice to give a high-level overview of
calamity
2014/07/08 09:47:20
Done. Changed for new algorithm.
|
- for (size_t i = 0; i < results.size(); ++i) { |
- ChromeSearchResult* result = results[i].result; |
- |
- ChromeSearchResult* ui_result = i < ui_results->item_count() ? |
- static_cast<ChromeSearchResult*>(ui_results->GetItemAt(i)) : NULL; |
- if (ui_result && ui_result->id() == result->id()) { |
- ui_result->set_title(result->title()); |
- ui_result->set_title_tags(result->title_tags()); |
- ui_result->set_details(result->details()); |
- ui_result->set_details_tags(result->details_tags()); |
- ui_results->NotifyItemsChanged(i, 1); |
+ typedef std::map<std::string, ChromeSearchResult*> IdToResultMap; |
+ |
+ IdToResultMap new_results_map; |
+ for (size_t i = 0; i < new_results.size(); ++i) |
Matt Giuca
2014/07/04 08:21:21
Use an iterator.
calamity
2014/07/08 09:47:21
Done.
|
+ new_results_map[new_results[i].result->id()] = new_results[i].result; |
+ |
+ // A map of the items in |ui_results| that takes ownership of the items. |
+ IdToResultMap ui_results_map; |
+ for (size_t i = 0; i < ui_results->item_count(); ++i) { |
+ ChromeSearchResult* ui_result = |
+ static_cast<ChromeSearchResult*>(ui_results->GetItemAt(i)); |
+ ui_results_map[ui_result->id()] = ui_result; |
+ } |
+ // We have to erase all results at once so that observers are notified with |
+ // meaningful indexes. |
Matt Giuca
2014/07/04 08:21:22
Does this mean observers will see a "remove" of a
calamity
2014/07/08 09:47:21
Yes. The alternative is to use a Move(), but the o
|
+ ui_results->RemoveAll(); |
+ |
+ // For each ui result, update its properties if it is in the new results, |
+ // otherwise delete it. |
+ std::vector<std::string> ids_to_delete; |
+ for (IdToResultMap::const_iterator ui_result_it = ui_results_map.begin(); |
+ ui_result_it != ui_results_map.end(); |
+ ++ui_result_it) { |
+ ChromeSearchResult* ui_result = ui_result_it->second; |
+ IdToResultMap::const_iterator result_it = |
+ new_results_map.find(ui_result->id()); |
+ if (result_it != new_results_map.end()) { |
+ ChromeSearchResult* new_result = result_it->second; |
Matt Giuca
2014/07/04 08:21:22
Can I suggest (the original code could have used t
calamity
2014/07/08 09:47:21
Done.
|
+ ui_result->set_title(new_result->title()); |
+ ui_result->set_title_tags(new_result->title_tags()); |
+ ui_result->set_details(new_result->details()); |
+ ui_result->set_details_tags(new_result->details_tags()); |
+ new_results_map.erase(result_it); |
Matt Giuca
2014/07/04 08:21:21
Is there a reason you need to erase results from n
|
} else { |
- if (ui_result) |
- ui_results->DeleteAt(i); |
- ui_results->AddAt(i, result->Duplicate().release()); |
+ ids_to_delete.push_back(ui_result->id()); |
} |
} |
- while (ui_results->item_count() > results.size()) |
- ui_results->DeleteAt(ui_results->item_count() - 1); |
+ for (size_t i = 0; i < ids_to_delete.size(); ++i) { |
+ delete ui_results_map[ids_to_delete[i]]; |
+ ui_results_map.erase(ids_to_delete[i]); |
+ } |
+ |
+ // Insert results in the order of |new_results|. |
Matt Giuca
2014/07/04 08:21:21
Before this comment, say:
// Now, ui_results_map c
calamity
2014/07/08 09:47:21
Done.
|
+ for (size_t i = 0; i < new_results.size(); ++i) { |
+ ChromeSearchResult* new_result = new_results[i].result; |
+ IdToResultMap::const_iterator ui_result_it = |
+ ui_results_map.find(new_result->id()); |
+ // |ui_results| takes ownership here. |
+ ui_results->Add(ui_result_it != ui_results_map.end() |
+ ? ui_result_it->second |
+ : new_result->Duplicate().release()); |
Matt Giuca
2014/07/04 08:21:21
Should you be calling NotifyItemsChanged here? The
calamity
2014/07/08 09:47:21
Not necessary as the add and remove are used to no
|
+ } |
} |
} // namespace |