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 |