| Index: ui/app_list/cocoa/apps_search_results_model_bridge.mm
|
| diff --git a/ui/app_list/cocoa/apps_search_results_model_bridge.mm b/ui/app_list/cocoa/apps_search_results_model_bridge.mm
|
| index 69a3205ef06bde137fa4495cb440776b61d1d066..ce6ede47e1798035e79955bb50dfeeea36ceab9a 100644
|
| --- a/ui/app_list/cocoa/apps_search_results_model_bridge.mm
|
| +++ b/ui/app_list/cocoa/apps_search_results_model_bridge.mm
|
| @@ -11,8 +11,31 @@
|
| #import "ui/app_list/cocoa/apps_search_results_controller.h"
|
| #include "ui/app_list/search_result.h"
|
| #include "ui/app_list/search_result_observer.h"
|
| +#import "ui/base/cocoa/controls/blue_label_button.h"
|
| #import "ui/base/cocoa/menu_controller.h"
|
|
|
| +namespace {
|
| +
|
| +// Padding on the left and right of action buttons.
|
| +const CGFloat kActionButtonPadding = 10;
|
| +
|
| +}
|
| +
|
| +// Action target for all the action buttons on a result row.
|
| +@interface ActionButtonTarget : NSObject {
|
| + @private
|
| + app_list::AppsSearchResultsModelBridge::ItemObserver* parent_;
|
| +}
|
| +
|
| +// Designated initializer.
|
| +- (id)initWithParent:
|
| + (app_list::AppsSearchResultsModelBridge::ItemObserver*)parent;
|
| +
|
| +// |sender| is the NSButton for the action.
|
| +- (void)onActionButtonClicked:(id)sender;
|
| +
|
| +@end
|
| +
|
| namespace app_list {
|
|
|
| class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver {
|
| @@ -22,11 +45,14 @@ class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver {
|
| // Cache the result, because the results array is updated before notifying
|
| // observers (which happens before deleting the SearchResult).
|
| result_ = [bridge_->parent_ results]->GetItemAt(index);
|
| + OnActionsChanged();
|
| result_->AddObserver(this);
|
| }
|
|
|
| virtual ~ItemObserver() {
|
| result_->RemoveObserver(this);
|
| + [action_button_ removeFromSuperview];
|
| + [action_button_ setTarget:nil];
|
| }
|
|
|
| NSMenu* GetContextMenu() {
|
| @@ -42,11 +68,23 @@ class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver {
|
| return [context_menu_controller_ menu];
|
| }
|
|
|
| + CGFloat GetActionButtonWidth() {
|
| + CGFloat width = NSWidth([action_button_ bounds]);
|
| + if (width != 0)
|
| + width += kActionButtonPadding;
|
| + return width;
|
| + }
|
| +
|
| + void InvokeActionAtIndex(int action_index) {
|
| + [[bridge_->parent_ delegate] invokeResultAction:result_
|
| + atIndex:action_index];
|
| + }
|
| +
|
| // SearchResultObserver overrides:
|
| virtual void OnIconChanged() OVERRIDE {
|
| bridge_->ReloadDataForItems(row_in_view_, 1);
|
| }
|
| - virtual void OnActionsChanged() OVERRIDE {}
|
| + virtual void OnActionsChanged() OVERRIDE;
|
| virtual void OnIsInstallingChanged() OVERRIDE {}
|
| virtual void OnPercentDownloadedChanged() OVERRIDE {}
|
| virtual void OnItemInstalled() OVERRIDE {}
|
| @@ -56,6 +94,8 @@ class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver {
|
| AppsSearchResultsModelBridge* bridge_; // Weak. Owns us.
|
| SearchResult* result_; // Weak. Owned by AppListModel::SearchResults.
|
| size_t row_in_view_;
|
| + base::scoped_nsobject<ActionButtonTarget> action_target_;
|
| + base::scoped_nsobject<NSButton> action_button_;
|
| base::scoped_nsobject<MenuController> context_menu_controller_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ItemObserver);
|
| @@ -70,6 +110,41 @@ void AppsSearchResultsModelBridge::ItemObserver::OnItemUninstalled() {
|
| afterDelay:0];
|
| }
|
|
|
| +void AppsSearchResultsModelBridge::ItemObserver::OnActionsChanged() {
|
| + [action_button_ removeFromSuperview];
|
| + action_button_.reset();
|
| + const SearchResult::Actions& actions = result_->actions();
|
| + if (actions.empty())
|
| + return;
|
| +
|
| + size_t action_index = 0;
|
| + const SearchResult::Action& action = actions[action_index];
|
| + if (action.label_text.empty() || actions.size() != 1) {
|
| + // TODO(tapted) Support multiple action buttons.
|
| + NOTIMPLEMENTED();
|
| + return;
|
| + }
|
| +
|
| + if (!action_target_)
|
| + action_target_.reset([[ActionButtonTarget alloc] initWithParent:this]);
|
| +
|
| + action_button_.reset([[BlueLabelButton alloc] initWithFrame:NSZeroRect]);
|
| + [action_button_ setTitle:base::SysUTF16ToNSString(action.label_text)];
|
| + [action_button_ setTarget:action_target_];
|
| + [action_button_ setAction:@selector(onActionButtonClicked:)];
|
| + [action_button_ setTag:action_index];
|
| + [action_button_ sizeToFit];
|
| + NSRect button_frame = [action_button_ frame];
|
| + NSRect cell_frame =
|
| + [[bridge_->parent_ tableView] frameOfCellAtColumn:0
|
| + row:row_in_view_];
|
| + NSPoint origin = NSMakePoint(
|
| + NSWidth(cell_frame) - NSWidth(button_frame) - kActionButtonPadding,
|
| + ceil(NSMidY(cell_frame) - NSMidY(button_frame)));
|
| + [action_button_ setFrameOrigin:origin];
|
| + [[bridge_->parent_ tableView] addSubview:action_button_];
|
| +}
|
| +
|
| AppsSearchResultsModelBridge::AppsSearchResultsModelBridge(
|
| AppsSearchResultsController* results_controller)
|
| : parent_(results_controller) {
|
| @@ -86,6 +161,11 @@ NSMenu* AppsSearchResultsModelBridge::MenuForItem(size_t index) {
|
| return item_observers_[index]->GetContextMenu();
|
| }
|
|
|
| +CGFloat AppsSearchResultsModelBridge::ActionButtonWidthForItem(size_t index) {
|
| + DCHECK_LT(index, item_observers_.size());
|
| + return item_observers_[index]->GetActionButtonWidth();
|
| +}
|
| +
|
| void AppsSearchResultsModelBridge::UpdateItemObservers() {
|
| DCHECK(item_observers_.empty());
|
| const size_t itemCount = [parent_ results]->item_count();
|
| @@ -135,3 +215,19 @@ void AppsSearchResultsModelBridge::ListItemsChanged(
|
| }
|
|
|
| } // namespace app_list
|
| +
|
| +@implementation ActionButtonTarget
|
| +
|
| +- (id)initWithParent:
|
| + (app_list::AppsSearchResultsModelBridge::ItemObserver*)parent {
|
| + if ((self = [super init])) {
|
| + parent_ = parent;
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (void)onActionButtonClicked:(id)sender {
|
| + parent_->InvokeActionAtIndex([sender tag]);
|
| +}
|
| +
|
| +@end
|
|
|