1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "ui/app_list/cocoa/apps_search_results_model_bridge.h"
7 #import <Cocoa/Cocoa.h>
9 #include "base/strings/sys_string_conversions.h"
10 #include "ui/app_list/app_list_model.h"
11 #import "ui/app_list/cocoa/apps_search_results_controller.h"
12 #include "ui/app_list/search_result.h"
13 #include "ui/app_list/search_result_observer.h"
14 #import "ui/base/cocoa/menu_controller.h"
18 class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver {
20 ItemObserver(AppsSearchResultsModelBridge* bridge, size_t index)
21 : bridge_(bridge), row_in_view_(index) {
22 // Cache the result, because the results array is updated before notifying
23 // observers (which happens before deleting the SearchResult).
24 result_ = [bridge_->parent_ results]->GetItemAt(index);
25 result_->AddObserver(this);
28 virtual ~ItemObserver() {
29 result_->RemoveObserver(this);
32 NSMenu* GetContextMenu() {
33 if (!context_menu_controller_) {
34 ui::MenuModel* menu_model = result_->GetContextMenuModel();
38 context_menu_controller_.reset(
39 [[MenuController alloc] initWithModel:menu_model
40 useWithPopUpButtonCell:NO]);
42 return [context_menu_controller_ menu];
45 // SearchResultObserver overrides:
46 virtual void OnIconChanged() OVERRIDE {
47 bridge_->ReloadDataForItems(row_in_view_, 1);
49 virtual void OnActionsChanged() OVERRIDE {}
50 virtual void OnIsInstallingChanged() OVERRIDE {}
51 virtual void OnPercentDownloadedChanged() OVERRIDE {}
52 virtual void OnItemInstalled() OVERRIDE {}
53 virtual void OnItemUninstalled() OVERRIDE;
56 AppsSearchResultsModelBridge* bridge_; // Weak. Owns us.
57 SearchResult* result_; // Weak. Owned by AppListModel::SearchResults.
59 base::scoped_nsobject<MenuController> context_menu_controller_;
61 DISALLOW_COPY_AND_ASSIGN(ItemObserver);
64 void AppsSearchResultsModelBridge::ItemObserver::OnItemUninstalled() {
65 // Performing the search again will destroy |this|, so post a task. This also
66 // ensures that the AppSearchProvider has observed the uninstall before
67 // performing the search again, otherwise it will provide a NULL result.
68 [[bridge_->parent_ delegate] performSelector:@selector(redoSearch)
73 AppsSearchResultsModelBridge::AppsSearchResultsModelBridge(
74 AppsSearchResultsController* results_controller)
75 : parent_(results_controller) {
76 UpdateItemObservers();
77 [parent_ results]->AddObserver(this);
80 AppsSearchResultsModelBridge::~AppsSearchResultsModelBridge() {
81 [parent_ results]->RemoveObserver(this);
84 NSMenu* AppsSearchResultsModelBridge::MenuForItem(size_t index) {
85 DCHECK_LT(index, item_observers_.size());
86 return item_observers_[index]->GetContextMenu();
89 void AppsSearchResultsModelBridge::UpdateItemObservers() {
90 DCHECK(item_observers_.empty());
91 const size_t itemCount = [parent_ results]->item_count();
92 for (size_t i = 0 ; i < itemCount; ++i)
93 item_observers_.push_back(new ItemObserver(this, i));
96 void AppsSearchResultsModelBridge::ReloadDataForItems(
97 size_t start, size_t count) const {
98 NSIndexSet* column = [NSIndexSet indexSetWithIndex:0];
100 [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(start, count)];
101 [[parent_ tableView] reloadDataForRowIndexes:rows
102 columnIndexes:column];
105 void AppsSearchResultsModelBridge::ListItemsAdded(
106 size_t start, size_t count) {
107 item_observers_.clear();
108 if (start == static_cast<size_t>([[parent_ tableView] numberOfRows]))
109 [[parent_ tableView] noteNumberOfRowsChanged];
111 [[parent_ tableView] reloadData];
112 UpdateItemObservers();
115 void AppsSearchResultsModelBridge::ListItemsRemoved(
116 size_t start, size_t count) {
117 item_observers_.clear();
118 if (start == [parent_ results]->item_count())
119 [[parent_ tableView] noteNumberOfRowsChanged];
121 [[parent_ tableView] reloadData];
122 UpdateItemObservers();
125 void AppsSearchResultsModelBridge::ListItemMoved(
126 size_t index, size_t target_index) {
130 void AppsSearchResultsModelBridge::ListItemsChanged(
131 size_t start, size_t count) {
132 item_observers_.clear();
133 ReloadDataForItems(start, count);
134 UpdateItemObservers();
137 } // namespace app_list