apps_search_results_model_bridge.mm revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "ui/app_list/cocoa/apps_search_results_model_bridge.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#import <Cocoa/Cocoa.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/sys_string_conversions.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/app_list/search_result.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/app_list/search_result_observer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "ui/base/cocoa/menu_controller.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace app_list {
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver {
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ItemObserver(AppsSearchResultsModelBridge* bridge, size_t index)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : bridge_(bridge), row_in_view_(index) {
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Cache the result, because the results array is updated before notifying
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // observers (which happens before deleting the SearchResult).
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result_ = bridge_->results_->GetItemAt(index);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result_->AddObserver(this);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~ItemObserver() {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result_->RemoveObserver(this);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSMenu* GetContextMenu() {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!context_menu_controller_) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_menu_controller_.reset(
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          [[MenuController alloc] initWithModel:result_->GetContextMenuModel()
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         useWithPopUpButtonCell:NO]);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return [context_menu_controller_ menu];
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SearchResultObserver overrides:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnIconChanged() OVERRIDE {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bridge_->ReloadDataForItems(row_in_view_, 1);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnActionsChanged() OVERRIDE {}
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnIsInstallingChanged() OVERRIDE {}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnPercentDownloadedChanged() OVERRIDE {}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppsSearchResultsModelBridge* bridge_;  // Weak. Owns us.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SearchResult* result_;  // Weak. Owned by AppListModel::SearchResults.
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t row_in_view_;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::scoped_nsobject<MenuController> context_menu_controller_;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ItemObserver);
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppsSearchResultsModelBridge::AppsSearchResultsModelBridge(
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppListModel::SearchResults* results_model,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NSTableView* results_table_view)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : results_(results_model),
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      table_view_([results_table_view retain]) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateItemObservers();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_->AddObserver(this);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppsSearchResultsModelBridge::~AppsSearchResultsModelBridge() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_->RemoveObserver(this);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSMenu* AppsSearchResultsModelBridge::MenuForItem(size_t index) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(index, item_observers_.size());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return item_observers_[index]->GetContextMenu();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppsSearchResultsModelBridge::UpdateItemObservers() {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(item_observers_.empty());
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t itemCount = results_->item_count();
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0 ; i < itemCount; ++i)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    item_observers_.push_back(new ItemObserver(this, i));
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppsSearchResultsModelBridge::ReloadDataForItems(
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t start, size_t count) const {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NSIndexSet* column = [NSIndexSet indexSetWithIndex:0];
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NSIndexSet* rows =
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(start, count)];
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [table_view_ reloadDataForRowIndexes:rows
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         columnIndexes:column];
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AppsSearchResultsModelBridge::ListItemsAdded(
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    size_t start, size_t count) {
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  item_observers_.clear();
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (start == static_cast<size_t>([table_view_ numberOfRows]))
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    [table_view_ noteNumberOfRowsChanged];
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    [table_view_ reloadData];
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateItemObservers();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AppsSearchResultsModelBridge::ListItemsRemoved(
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t start, size_t count) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  item_observers_.clear();
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (start == results_->item_count())
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    [table_view_ noteNumberOfRowsChanged];
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    [table_view_ reloadData];
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateItemObservers();
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppsSearchResultsModelBridge::ListItemMoved(
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t index, size_t target_index) {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppsSearchResultsModelBridge::ListItemsChanged(
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    size_t start, size_t count) {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  item_observers_.clear();
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ReloadDataForItems(start, count);
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UpdateItemObservers();
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace app_list
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)