Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1066)

Side by Side Diff: chrome/browser/ui/cocoa/extensions/browser_action_button.mm

Issue 869873008: [Extensions Toolbar] Move some popup logic to be platform-agnostic (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/extensions/browser_action_button.h" 5 #import "chrome/browser/ui/cocoa/extensions/browser_action_button.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/weak_ptr.h" 11 #include "base/memory/weak_ptr.h"
12 #include "base/strings/sys_string_conversions.h" 12 #include "base/strings/sys_string_conversions.h"
13 #include "chrome/browser/extensions/extension_context_menu_model.h"
14 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h" 14 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_window.h" 15 #include "chrome/browser/ui/browser_window.h"
17 #import "chrome/browser/ui/cocoa/browser_window_controller.h" 16 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
18 #import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h" 17 #import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
19 #import "chrome/browser/ui/cocoa/themed_window.h" 18 #import "chrome/browser/ui/cocoa/themed_window.h"
20 #import "chrome/browser/ui/cocoa/toolbar/toolbar_action_view_delegate_cocoa.h" 19 #import "chrome/browser/ui/cocoa/toolbar/toolbar_action_view_delegate_cocoa.h"
21 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" 20 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
22 #import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h" 21 #import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h"
23 #include "chrome/browser/ui/extensions/extension_action_view_controller.h"
24 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" 22 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
25 #include "grit/theme_resources.h" 23 #include "grit/theme_resources.h"
26 #include "skia/ext/skia_utils_mac.h" 24 #include "skia/ext/skia_utils_mac.h"
27 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h " 25 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h "
28 #import "ui/base/cocoa/menu_controller.h" 26 #import "ui/base/cocoa/menu_controller.h"
29 #include "ui/gfx/canvas_skia_paint.h" 27 #include "ui/gfx/canvas_skia_paint.h"
30 #include "ui/gfx/geometry/rect.h" 28 #include "ui/gfx/geometry/rect.h"
31 #include "ui/gfx/image/image.h" 29 #include "ui/gfx/image/image.h"
32 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" 30 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
33 31
34 NSString* const kBrowserActionButtonDraggingNotification = 32 NSString* const kBrowserActionButtonDraggingNotification =
35 @"BrowserActionButtonDraggingNotification"; 33 @"BrowserActionButtonDraggingNotification";
36 NSString* const kBrowserActionButtonDragEndNotification = 34 NSString* const kBrowserActionButtonDragEndNotification =
37 @"BrowserActionButtonDragEndNotification"; 35 @"BrowserActionButtonDragEndNotification";
38 36
39 static const CGFloat kBrowserActionBadgeOriginYOffset = 5; 37 static const CGFloat kBrowserActionBadgeOriginYOffset = 5;
40 static const CGFloat kAnimationDuration = 0.2; 38 static const CGFloat kAnimationDuration = 0.2;
41 static const CGFloat kMinimumDragDistance = 5; 39 static const CGFloat kMinimumDragDistance = 5;
42 40
41 @interface BrowserActionButton (Private)
Avi (use Gerrit) 2015/01/29 02:59:26 You can use a class extension by dropping the cont
Devlin 2015/01/29 17:42:08 Ooh, class extensions vs categories. Nifty. Than
42 - (void)endDrag;
43 - (void)updateHighlightedState;
44 @end
45
43 // A class to bridge the ToolbarActionViewController and the 46 // A class to bridge the ToolbarActionViewController and the
44 // BrowserActionButton. 47 // BrowserActionButton.
45 class ToolbarActionViewDelegateBridge : public ToolbarActionViewDelegateCocoa { 48 class ToolbarActionViewDelegateBridge : public ToolbarActionViewDelegateCocoa {
46 public: 49 public:
47 ToolbarActionViewDelegateBridge(BrowserActionButton* owner, 50 ToolbarActionViewDelegateBridge(BrowserActionButton* owner,
48 BrowserActionsController* controller, 51 BrowserActionsController* controller,
49 ToolbarActionViewController* viewController); 52 ToolbarActionViewController* viewController);
50 ~ToolbarActionViewDelegateBridge() override; 53 ~ToolbarActionViewDelegateBridge() override;
51 54
52 // Shows the context menu for the owning action. 55 // Shows the context menu for the owning action.
53 void ShowContextMenu(); 56 void ShowContextMenu();
54 57
58 bool user_shown_popup_visible() const { return user_shown_popup_visible_; }
59
55 private: 60 private:
56 // ToolbarActionViewDelegateCocoa: 61 // ToolbarActionViewDelegateCocoa:
57 ToolbarActionViewController* GetPreferredPopupViewController() override; 62 ToolbarActionViewController* GetPreferredPopupViewController() override;
58 content::WebContents* GetCurrentWebContents() const override; 63 content::WebContents* GetCurrentWebContents() const override;
59 void UpdateState() override; 64 void UpdateState() override;
65 void OnPopupShown(bool by_user) override;
66 void OnPopupClosed() override;
60 NSPoint GetPopupPoint() override; 67 NSPoint GetPopupPoint() override;
61 68
62 // A helper method to implement showing the context menu. 69 // A helper method to implement showing the context menu.
63 void DoShowContextMenu(); 70 void DoShowContextMenu();
64 71
65 // The owning button. Weak. 72 // The owning button. Weak.
66 BrowserActionButton* owner_; 73 BrowserActionButton* owner_;
67 74
68 // The BrowserActionsController that owns the button. Weak. 75 // The BrowserActionsController that owns the button. Weak.
69 BrowserActionsController* controller_; 76 BrowserActionsController* controller_;
70 77
71 // The ToolbarActionViewController for which this is the delegate. Weak. 78 // The ToolbarActionViewController for which this is the delegate. Weak.
72 ToolbarActionViewController* viewController_; 79 ToolbarActionViewController* viewController_;
73 80
81 // Whether or not a popup is visible from a user action.
82 bool user_shown_popup_visible_;
83
74 base::WeakPtrFactory<ToolbarActionViewDelegateBridge> weakFactory_; 84 base::WeakPtrFactory<ToolbarActionViewDelegateBridge> weakFactory_;
75 85
76 DISALLOW_COPY_AND_ASSIGN(ToolbarActionViewDelegateBridge); 86 DISALLOW_COPY_AND_ASSIGN(ToolbarActionViewDelegateBridge);
77 }; 87 };
78 88
79 ToolbarActionViewDelegateBridge::ToolbarActionViewDelegateBridge( 89 ToolbarActionViewDelegateBridge::ToolbarActionViewDelegateBridge(
80 BrowserActionButton* owner, 90 BrowserActionButton* owner,
81 BrowserActionsController* controller, 91 BrowserActionsController* controller,
82 ToolbarActionViewController* viewController) 92 ToolbarActionViewController* viewController)
83 : owner_(owner), 93 : owner_(owner),
84 controller_(controller), 94 controller_(controller),
85 viewController_(viewController), 95 viewController_(viewController),
96 user_shown_popup_visible_(false),
86 weakFactory_(this) { 97 weakFactory_(this) {
87 viewController_->SetDelegate(this); 98 viewController_->SetDelegate(this);
88 } 99 }
89 100
90 ToolbarActionViewDelegateBridge::~ToolbarActionViewDelegateBridge() { 101 ToolbarActionViewDelegateBridge::~ToolbarActionViewDelegateBridge() {
91 viewController_->SetDelegate(nullptr); 102 viewController_->SetDelegate(nullptr);
92 } 103 }
93 104
94 void ToolbarActionViewDelegateBridge::ShowContextMenu() { 105 void ToolbarActionViewDelegateBridge::ShowContextMenu() {
95 // We should only be showing the context menu in this way if we're doing so 106 // We should only be showing the context menu in this way if we're doing so
(...skipping 25 matching lines...) Expand all
121 132
122 content::WebContents* ToolbarActionViewDelegateBridge::GetCurrentWebContents() 133 content::WebContents* ToolbarActionViewDelegateBridge::GetCurrentWebContents()
123 const { 134 const {
124 return [controller_ currentWebContents]; 135 return [controller_ currentWebContents];
125 } 136 }
126 137
127 void ToolbarActionViewDelegateBridge::UpdateState() { 138 void ToolbarActionViewDelegateBridge::UpdateState() {
128 [owner_ updateState]; 139 [owner_ updateState];
129 } 140 }
130 141
142 void ToolbarActionViewDelegateBridge::OnPopupShown(bool by_user) {
143 if (by_user)
144 user_shown_popup_visible_ = true;
145 [owner_ updateHighlightedState];
146 }
147
148 void ToolbarActionViewDelegateBridge::OnPopupClosed() {
149 user_shown_popup_visible_ = false;
150 [owner_ updateHighlightedState];
151 }
152
131 NSPoint ToolbarActionViewDelegateBridge::GetPopupPoint() { 153 NSPoint ToolbarActionViewDelegateBridge::GetPopupPoint() {
132 return [controller_ popupPointForId:[owner_ viewController]->GetId()]; 154 return [controller_ popupPointForId:[owner_ viewController]->GetId()];
133 } 155 }
134 156
135 void ToolbarActionViewDelegateBridge::DoShowContextMenu() { 157 void ToolbarActionViewDelegateBridge::DoShowContextMenu() {
136 NSButton* wrenchButton = 158 NSButton* wrenchButton =
137 [[[BrowserWindowController browserWindowControllerForWindow: 159 [[[BrowserWindowController browserWindowControllerForWindow:
138 [controller_ browser]->window()->GetNativeWindow()] 160 [controller_ browser]->window()->GetNativeWindow()]
139 toolbarController] wrenchButton]; 161 toolbarController] wrenchButton];
140 // The point the menu shows matches that of the normal wrench menu - that is, 162 // The point the menu shows matches that of the normal wrench menu - that is,
(...skipping 10 matching lines...) Expand all
151 atLocation:menuPoint 173 atLocation:menuPoint
152 inView:wrenchButton]; 174 inView:wrenchButton];
153 [[wrenchButton cell] setHighlighted:NO]; 175 [[wrenchButton cell] setHighlighted:NO];
154 } 176 }
155 177
156 @interface BrowserActionCell (Internals) 178 @interface BrowserActionCell (Internals)
157 - (void)drawBadgeWithinFrame:(NSRect)frame 179 - (void)drawBadgeWithinFrame:(NSRect)frame
158 forWebContents:(content::WebContents*)webContents; 180 forWebContents:(content::WebContents*)webContents;
159 @end 181 @end
160 182
161 @interface BrowserActionButton (Private)
162 - (void)endDrag;
163 @end
164
165 @implementation BrowserActionButton 183 @implementation BrowserActionButton
166 184
167 @synthesize isBeingDragged = isBeingDragged_; 185 @synthesize isBeingDragged = isBeingDragged_;
168 186
169 + (Class)cellClass { 187 + (Class)cellClass {
170 return [BrowserActionCell class]; 188 return [BrowserActionCell class];
171 } 189 }
172 190
173 - (id)initWithFrame:(NSRect)frame 191 - (id)initWithFrame:(NSRect)frame
174 viewController:(ToolbarActionViewController*)viewController 192 viewController:(ToolbarActionViewController*)viewController
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 // etc). When the mouse leaves, we get no indication (no mouseUp), so we can't 264 // etc). When the mouse leaves, we get no indication (no mouseUp), so we can't
247 // even handle that case - and are left in the middle of a drag. Instead, we 265 // even handle that case - and are left in the middle of a drag. Instead, we
248 // have to simply disable dragging. 266 // have to simply disable dragging.
249 // 267 //
250 // NOTE(devlin): If we use a greedy event loop that consumes all incoming 268 // NOTE(devlin): If we use a greedy event loop that consumes all incoming
251 // events (i.e. using [NSWindow nextEventMatchingMask]), we can make this 269 // events (i.e. using [NSWindow nextEventMatchingMask]), we can make this
252 // work. The downside to that is that all other events are lost. Disable this 270 // work. The downside to that is that all other events are lost. Disable this
253 // for now, and revisit it at a later date. 271 // for now, and revisit it at a later date.
254 if (NSPointInRect(location, [self bounds]) && 272 if (NSPointInRect(location, [self bounds]) &&
255 ![browserActionsController_ isOverflow]) { 273 ![browserActionsController_ isOverflow]) {
256 [[self cell] setHighlighted:YES];
257 dragCouldStart_ = YES; 274 dragCouldStart_ = YES;
258 dragStartPoint_ = [self convertPoint:[theEvent locationInWindow] 275 dragStartPoint_ = [self convertPoint:[theEvent locationInWindow]
259 fromView:nil]; 276 fromView:nil];
277 [self updateHighlightedState];
260 } 278 }
261 } 279 }
262 280
263 - (void)mouseDragged:(NSEvent*)theEvent { 281 - (void)mouseDragged:(NSEvent*)theEvent {
264 if (!dragCouldStart_) 282 if (!dragCouldStart_)
265 return; 283 return;
266 284
267 NSPoint eventPoint = [theEvent locationInWindow]; 285 NSPoint eventPoint = [theEvent locationInWindow];
268 if (!isBeingDragged_) { 286 if (!isBeingDragged_) {
269 // Don't initiate a drag until it moves at least kMinimumDragDistance. 287 // Don't initiate a drag until it moves at least kMinimumDragDistance.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 // Only perform the click if we didn't drag the button. 339 // Only perform the click if we didn't drag the button.
322 [self performClick:self]; 340 [self performClick:self];
323 } else { 341 } else {
324 // Make sure an ESC to end a drag doesn't trigger 2 endDrags. 342 // Make sure an ESC to end a drag doesn't trigger 2 endDrags.
325 if (isBeingDragged_) { 343 if (isBeingDragged_) {
326 [self endDrag]; 344 [self endDrag];
327 } else { 345 } else {
328 [super mouseUp:theEvent]; 346 [super mouseUp:theEvent];
329 } 347 }
330 } 348 }
349 [self updateHighlightedState];
331 } 350 }
332 351
333 - (void)endDrag { 352 - (void)endDrag {
334 isBeingDragged_ = NO; 353 isBeingDragged_ = NO;
335 [[NSNotificationCenter defaultCenter] 354 [[NSNotificationCenter defaultCenter]
336 postNotificationName:kBrowserActionButtonDragEndNotification object:self]; 355 postNotificationName:kBrowserActionButtonDragEndNotification object:self];
337 [[self cell] setHighlighted:NO]; 356 }
357
358 - (void)updateHighlightedState {
359 // The button's cell is highlighted if either the popup is showing by a user
360 // action, or the user is about to drag the button, unless the button is
361 // overflowed (in which case it is never highlighted).
362 if ([self superview] && ![browserActionsController_ isOverflow]) {
363 BOOL highlighted = viewControllerDelegate_->user_shown_popup_visible() ||
364 dragCouldStart_;
365 [[self cell] setHighlighted:highlighted];
366 }
338 } 367 }
339 368
340 - (void)setFrame:(NSRect)frameRect animate:(BOOL)animate { 369 - (void)setFrame:(NSRect)frameRect animate:(BOOL)animate {
341 if (!animate) { 370 if (!animate) {
342 [self setFrame:frameRect]; 371 [self setFrame:frameRect];
343 } else { 372 } else {
344 if ([moveAnimation_ isAnimating]) 373 if ([moveAnimation_ isAnimating])
345 [moveAnimation_ stopAnimation]; 374 [moveAnimation_ stopAnimation];
346 375
347 NSDictionary* animationDictionary = @{ 376 NSDictionary* animationDictionary = @{
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 - (ui::ThemeProvider*)themeProviderForWindow:(NSWindow*)window { 527 - (ui::ThemeProvider*)themeProviderForWindow:(NSWindow*)window {
499 ui::ThemeProvider* themeProvider = [window themeProvider]; 528 ui::ThemeProvider* themeProvider = [window themeProvider];
500 if (!themeProvider) 529 if (!themeProvider)
501 themeProvider = 530 themeProvider =
502 [[browserActionsController_ browser]->window()->GetNativeWindow() 531 [[browserActionsController_ browser]->window()->GetNativeWindow()
503 themeProvider]; 532 themeProvider];
504 return themeProvider; 533 return themeProvider;
505 } 534 }
506 535
507 @end 536 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698