| OLD | NEW |
| 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_actions_controller.h" | 5 #import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h
" | 31 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h
" |
| 32 #include "ui/base/cocoa/appkit_utils.h" | 32 #include "ui/base/cocoa/appkit_utils.h" |
| 33 #include "ui/base/cocoa/cocoa_base_utils.h" | 33 #include "ui/base/cocoa/cocoa_base_utils.h" |
| 34 #include "ui/base/material_design/material_design_controller.h" | 34 #include "ui/base/material_design/material_design_controller.h" |
| 35 | 35 |
| 36 NSString* const kBrowserActionVisibilityChangedNotification = | 36 NSString* const kBrowserActionVisibilityChangedNotification = |
| 37 @"BrowserActionVisibilityChangedNotification"; | 37 @"BrowserActionVisibilityChangedNotification"; |
| 38 | 38 |
| 39 namespace { | 39 namespace { |
| 40 | 40 |
| 41 const CGFloat kAnimationDuration = 0.2; | |
| 42 | |
| 43 const CGFloat kChevronWidth = 18; | |
| 44 | |
| 45 // How far to inset from the bottom of the view to get the top border | 41 // How far to inset from the bottom of the view to get the top border |
| 46 // of the popup 2px below the bottom of the Omnibox. | 42 // of the popup 2px below the bottom of the Omnibox. |
| 47 const CGFloat kBrowserActionBubbleYOffset = 3.0; | 43 const CGFloat kBrowserActionBubbleYOffset = 3.0; |
| 48 | 44 |
| 49 } // namespace | 45 } // namespace |
| 50 | 46 |
| 51 @interface BrowserActionsController(Private) | 47 @interface BrowserActionsController(Private) |
| 52 | 48 |
| 53 // Creates and adds a view for the given |action| at |index|. | 49 // Creates and adds a view for the given |action| at |index|. |
| 54 - (void)addViewForAction:(ToolbarActionViewController*)action | 50 - (void)addViewForAction:(ToolbarActionViewController*)action |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 // found. | 84 // found. |
| 89 - (BrowserActionButton*)buttonForId:(const std::string&)id; | 85 - (BrowserActionButton*)buttonForId:(const std::string&)id; |
| 90 | 86 |
| 91 // Returns the button at the given index. This is just a wrapper around | 87 // Returns the button at the given index. This is just a wrapper around |
| 92 // [NSArray objectAtIndex:], since that technically defaults to returning ids | 88 // [NSArray objectAtIndex:], since that technically defaults to returning ids |
| 93 // (and can cause compile errors). | 89 // (and can cause compile errors). |
| 94 - (BrowserActionButton*)buttonAtIndex:(NSUInteger)index; | 90 - (BrowserActionButton*)buttonAtIndex:(NSUInteger)index; |
| 95 | 91 |
| 96 // Notification handlers for events registered by the class. | 92 // Notification handlers for events registered by the class. |
| 97 | 93 |
| 98 // Updates each button's opacity, the cursor rects and chevron position. | 94 // Updates each button's opacity and the cursor rects. |
| 99 - (void)containerFrameChanged:(NSNotification*)notification; | 95 - (void)containerFrameChanged:(NSNotification*)notification; |
| 100 | 96 |
| 101 // Hides the chevron and unhides every hidden button so that dragging the | 97 // Unhides every hidden button so that dragging the container out smoothly shows |
| 102 // container out smoothly shows the Browser Action buttons. | 98 // the Browser Action buttons. |
| 103 - (void)containerDragStart:(NSNotification*)notification; | 99 - (void)containerDragStart:(NSNotification*)notification; |
| 104 | 100 |
| 105 // Determines which buttons need to be hidden based on the new size, hides them | 101 // Determines which buttons need to be hidden based on the new size and hides |
| 106 // and updates the chevron overflow menu. Also fires a notification to let the | 102 // them. Also fires a notification to let the toolbar know that the drag has |
| 107 // toolbar know that the drag has finished. | 103 // finished. |
| 108 - (void)containerDragFinished:(NSNotification*)notification; | 104 - (void)containerDragFinished:(NSNotification*)notification; |
| 109 | 105 |
| 110 // Notifies the controlling ToolbarActionsBar that any running animation has | 106 // Notifies the controlling ToolbarActionsBar that any running animation has |
| 111 // ended. | 107 // ended. |
| 112 - (void)containerAnimationEnded:(NSNotification*)notification; | 108 - (void)containerAnimationEnded:(NSNotification*)notification; |
| 113 | 109 |
| 114 // Processes a key event from the container. | 110 // Processes a key event from the container. |
| 115 - (void)containerKeyEvent:(NSNotification*)notification; | 111 - (void)containerKeyEvent:(NSNotification*)notification; |
| 116 | 112 |
| 117 // Adjusts the position of the surrounding action buttons depending on where the | 113 // Adjusts the position of the surrounding action buttons depending on where the |
| (...skipping 13 matching lines...) Expand all Loading... |
| 131 withBounds:(NSRect)bounds; | 127 withBounds:(NSRect)bounds; |
| 132 | 128 |
| 133 // Moves the given button both visually and within the toolbar model to the | 129 // Moves the given button both visually and within the toolbar model to the |
| 134 // specified index. | 130 // specified index. |
| 135 - (void)moveButton:(BrowserActionButton*)button | 131 - (void)moveButton:(BrowserActionButton*)button |
| 136 toIndex:(NSUInteger)index; | 132 toIndex:(NSUInteger)index; |
| 137 | 133 |
| 138 // Handles clicks for BrowserActionButtons. | 134 // Handles clicks for BrowserActionButtons. |
| 139 - (BOOL)browserActionClicked:(BrowserActionButton*)button; | 135 - (BOOL)browserActionClicked:(BrowserActionButton*)button; |
| 140 | 136 |
| 141 // The reason |frame| is specified in these chevron functions is because the | |
| 142 // container may be animating and the end frame of the animation should be | |
| 143 // passed instead of the current frame (which may be off and cause the chevron | |
| 144 // to jump at the end of its animation). | |
| 145 | |
| 146 // Shows the overflow chevron button depending on whether there are any hidden | |
| 147 // extensions within the frame given. | |
| 148 - (void)showChevronIfNecessaryInFrame:(NSRect)frame; | |
| 149 | |
| 150 // Moves the chevron to its correct position within |frame|. | |
| 151 - (void)updateChevronPositionInFrame:(NSRect)frame; | |
| 152 | |
| 153 // Shows or hides the chevron in the given |frame|. | |
| 154 - (void)setChevronHidden:(BOOL)hidden | |
| 155 inFrame:(NSRect)frame; | |
| 156 | |
| 157 // Handles when a menu item within the chevron overflow menu is selected. | |
| 158 - (void)chevronItemSelected:(id)menuItem; | |
| 159 | |
| 160 // Updates the container's grippy cursor based on the number of hidden buttons. | 137 // Updates the container's grippy cursor based on the number of hidden buttons. |
| 161 - (void)updateGrippyCursors; | 138 - (void)updateGrippyCursors; |
| 162 | 139 |
| 163 // Returns the associated ToolbarController. | 140 // Returns the associated ToolbarController. |
| 164 - (ToolbarController*)toolbarController; | 141 - (ToolbarController*)toolbarController; |
| 165 | 142 |
| 166 // Creates a message bubble with the given |delegate|. | 143 // Creates a message bubble with the given |delegate|. |
| 167 - (void)createMessageBubble: | 144 - (void)createMessageBubble: |
| 168 (std::unique_ptr<ToolbarActionsBarBubbleDelegate>)delegate; | 145 (std::unique_ptr<ToolbarActionsBarBubbleDelegate>)delegate; |
| 169 | 146 |
| 170 // Called when the window for the active bubble is closing, and sets the active | 147 // Called when the window for the active bubble is closing, and sets the active |
| 171 // bubble to nil. | 148 // bubble to nil. |
| 172 - (void)bubbleWindowClosing:(NSNotification*)notification; | 149 - (void)bubbleWindowClosing:(NSNotification*)notification; |
| 173 | 150 |
| 174 // Sets the current focused view. Should only be used for the overflow | 151 // Sets the current focused view. Should only be used for the overflow |
| 175 // container. | 152 // container. |
| 176 - (void)setFocusedViewIndex:(NSInteger)index; | 153 - (void)setFocusedViewIndex:(NSInteger)index; |
| 177 | 154 |
| 178 @end | 155 @end |
| 179 | 156 |
| 180 // A subclass of MenuButton that draws the chevron button in MD style. | |
| 181 @interface ChevronMenuButton : MenuButton | |
| 182 @end | |
| 183 | |
| 184 @implementation ChevronMenuButton | |
| 185 | |
| 186 - (gfx::VectorIconId)vectorIconId { | |
| 187 return gfx::VectorIconId::OVERFLOW_CHEVRON; | |
| 188 } | |
| 189 | |
| 190 @end | |
| 191 | |
| 192 namespace { | 157 namespace { |
| 193 | 158 |
| 194 // A bridge between the ToolbarActionsBar and the BrowserActionsController. | 159 // A bridge between the ToolbarActionsBar and the BrowserActionsController. |
| 195 class ToolbarActionsBarBridge : public ToolbarActionsBarDelegate { | 160 class ToolbarActionsBarBridge : public ToolbarActionsBarDelegate { |
| 196 public: | 161 public: |
| 197 explicit ToolbarActionsBarBridge(BrowserActionsController* controller); | 162 explicit ToolbarActionsBarBridge(BrowserActionsController* controller); |
| 198 ~ToolbarActionsBarBridge() override; | 163 ~ToolbarActionsBarBridge() override; |
| 199 | 164 |
| 200 BrowserActionsController* controller_for_test() { return controller_; } | 165 BrowserActionsController* controller_for_test() { return controller_; } |
| 201 | 166 |
| 202 private: | 167 private: |
| 203 // ToolbarActionsBarDelegate: | 168 // ToolbarActionsBarDelegate: |
| 204 void AddViewForAction(ToolbarActionViewController* action, | 169 void AddViewForAction(ToolbarActionViewController* action, |
| 205 size_t index) override; | 170 size_t index) override; |
| 206 void RemoveViewForAction(ToolbarActionViewController* action) override; | 171 void RemoveViewForAction(ToolbarActionViewController* action) override; |
| 207 void RemoveAllViews() override; | 172 void RemoveAllViews() override; |
| 208 void Redraw(bool order_changed) override; | 173 void Redraw(bool order_changed) override; |
| 209 void ResizeAndAnimate(gfx::Tween::Type tween_type, | 174 void ResizeAndAnimate(gfx::Tween::Type tween_type, |
| 210 int target_width, | 175 int target_width) override; |
| 211 bool suppress_chevron) override; | |
| 212 void SetChevronVisibility(bool chevron_visible) override; | |
| 213 int GetWidth(GetWidthTime get_width_time) const override; | 176 int GetWidth(GetWidthTime get_width_time) const override; |
| 214 bool IsAnimating() const override; | 177 bool IsAnimating() const override; |
| 215 void StopAnimating() override; | 178 void StopAnimating() override; |
| 216 int GetChevronWidth() const override; | |
| 217 void ShowToolbarActionBubble( | 179 void ShowToolbarActionBubble( |
| 218 std::unique_ptr<ToolbarActionsBarBubbleDelegate> bubble) override; | 180 std::unique_ptr<ToolbarActionsBarBubbleDelegate> bubble) override; |
| 219 | 181 |
| 220 // The owning BrowserActionsController; weak. | 182 // The owning BrowserActionsController; weak. |
| 221 BrowserActionsController* controller_; | 183 BrowserActionsController* controller_; |
| 222 | 184 |
| 223 DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBarBridge); | 185 DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBarBridge); |
| 224 }; | 186 }; |
| 225 | 187 |
| 226 ToolbarActionsBarBridge::ToolbarActionsBarBridge( | 188 ToolbarActionsBarBridge::ToolbarActionsBarBridge( |
| (...skipping 18 matching lines...) Expand all Loading... |
| 245 | 207 |
| 246 void ToolbarActionsBarBridge::RemoveAllViews() { | 208 void ToolbarActionsBarBridge::RemoveAllViews() { |
| 247 [controller_ removeAllViews]; | 209 [controller_ removeAllViews]; |
| 248 } | 210 } |
| 249 | 211 |
| 250 void ToolbarActionsBarBridge::Redraw(bool order_changed) { | 212 void ToolbarActionsBarBridge::Redraw(bool order_changed) { |
| 251 [controller_ redraw]; | 213 [controller_ redraw]; |
| 252 } | 214 } |
| 253 | 215 |
| 254 void ToolbarActionsBarBridge::ResizeAndAnimate(gfx::Tween::Type tween_type, | 216 void ToolbarActionsBarBridge::ResizeAndAnimate(gfx::Tween::Type tween_type, |
| 255 int target_width, | 217 int target_width) { |
| 256 bool suppress_chevron) { | |
| 257 [controller_ resizeContainerToWidth:target_width]; | 218 [controller_ resizeContainerToWidth:target_width]; |
| 258 } | 219 } |
| 259 | 220 |
| 260 void ToolbarActionsBarBridge::SetChevronVisibility(bool chevron_visible) { | |
| 261 [controller_ setChevronHidden:!chevron_visible | |
| 262 inFrame:[[controller_ containerView] frame]]; | |
| 263 } | |
| 264 | |
| 265 int ToolbarActionsBarBridge::GetWidth(GetWidthTime get_width_time) const { | 221 int ToolbarActionsBarBridge::GetWidth(GetWidthTime get_width_time) const { |
| 266 NSRect frame = | 222 NSRect frame = |
| 267 get_width_time == ToolbarActionsBarDelegate::GET_WIDTH_AFTER_ANIMATION | 223 get_width_time == ToolbarActionsBarDelegate::GET_WIDTH_AFTER_ANIMATION |
| 268 ? [[controller_ containerView] animationEndFrame] | 224 ? [[controller_ containerView] animationEndFrame] |
| 269 : [[controller_ containerView] frame]; | 225 : [[controller_ containerView] frame]; |
| 270 return NSWidth(frame); | 226 return NSWidth(frame); |
| 271 } | 227 } |
| 272 | 228 |
| 273 bool ToolbarActionsBarBridge::IsAnimating() const { | 229 bool ToolbarActionsBarBridge::IsAnimating() const { |
| 274 return [[controller_ containerView] isAnimating]; | 230 return [[controller_ containerView] isAnimating]; |
| 275 } | 231 } |
| 276 | 232 |
| 277 void ToolbarActionsBarBridge::StopAnimating() { | 233 void ToolbarActionsBarBridge::StopAnimating() { |
| 278 // Unfortunately, animating the browser actions container affects neighboring | 234 // Unfortunately, animating the browser actions container affects neighboring |
| 279 // views (like the omnibox), which could also be animating. Because of this, | 235 // views (like the omnibox), which could also be animating. Because of this, |
| 280 // instead of just ending the animation, the cleanest way to terminate is to | 236 // instead of just ending the animation, the cleanest way to terminate is to |
| 281 // "animate" to the current frame. | 237 // "animate" to the current frame. |
| 282 [controller_ resizeContainerToWidth: | 238 [controller_ resizeContainerToWidth: |
| 283 NSWidth([[controller_ containerView] frame])]; | 239 NSWidth([[controller_ containerView] frame])]; |
| 284 } | 240 } |
| 285 | 241 |
| 286 int ToolbarActionsBarBridge::GetChevronWidth() const { | |
| 287 return kChevronWidth; | |
| 288 } | |
| 289 | |
| 290 void ToolbarActionsBarBridge::ShowToolbarActionBubble( | 242 void ToolbarActionsBarBridge::ShowToolbarActionBubble( |
| 291 std::unique_ptr<ToolbarActionsBarBubbleDelegate> bubble) { | 243 std::unique_ptr<ToolbarActionsBarBubbleDelegate> bubble) { |
| 292 [controller_ createMessageBubble:std::move(bubble)]; | 244 [controller_ createMessageBubble:std::move(bubble)]; |
| 293 } | 245 } |
| 294 | 246 |
| 295 } // namespace | 247 } // namespace |
| 296 | 248 |
| 297 @implementation BrowserActionsController | 249 @implementation BrowserActionsController |
| 298 | 250 |
| 299 @synthesize containerView = containerView_; | 251 @synthesize containerView = containerView_; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 name:kBrowserActionsContainerReceivedKeyEvent | 301 name:kBrowserActionsContainerReceivedKeyEvent |
| 350 object:containerView_]; | 302 object:containerView_]; |
| 351 // Listen for a finished drag from any button to make sure each open window | 303 // Listen for a finished drag from any button to make sure each open window |
| 352 // stays in sync. | 304 // stays in sync. |
| 353 [[NSNotificationCenter defaultCenter] | 305 [[NSNotificationCenter defaultCenter] |
| 354 addObserver:self | 306 addObserver:self |
| 355 selector:@selector(actionButtonDragFinished:) | 307 selector:@selector(actionButtonDragFinished:) |
| 356 name:kBrowserActionButtonDragEndNotification | 308 name:kBrowserActionButtonDragEndNotification |
| 357 object:nil]; | 309 object:nil]; |
| 358 | 310 |
| 359 suppressChevron_ = NO; | |
| 360 if (toolbarActionsBar_->platform_settings().chevron_enabled) { | |
| 361 chevronAnimation_.reset([[NSViewAnimation alloc] init]); | |
| 362 [chevronAnimation_ gtm_setDuration:kAnimationDuration | |
| 363 eventMask:NSLeftMouseUpMask]; | |
| 364 [chevronAnimation_ setAnimationBlockingMode:NSAnimationNonblocking]; | |
| 365 } | |
| 366 | |
| 367 if (isOverflow_) | 311 if (isOverflow_) |
| 368 toolbarActionsBar_->SetOverflowRowWidth(NSWidth([containerView_ frame])); | 312 toolbarActionsBar_->SetOverflowRowWidth(NSWidth([containerView_ frame])); |
| 369 | 313 |
| 370 buttons_.reset([[NSMutableArray alloc] init]); | 314 buttons_.reset([[NSMutableArray alloc] init]); |
| 371 toolbarActionsBar_->CreateActions(); | 315 toolbarActionsBar_->CreateActions(); |
| 372 [self showChevronIfNecessaryInFrame:[containerView_ frame]]; | |
| 373 [self updateGrippyCursors]; | 316 [self updateGrippyCursors]; |
| 374 [container setIsOverflow:isOverflow_]; | 317 [container setIsOverflow:isOverflow_]; |
| 375 | 318 |
| 376 focusedViewIndex_ = -1; | 319 focusedViewIndex_ = -1; |
| 377 } | 320 } |
| 378 | 321 |
| 379 return self; | 322 return self; |
| 380 } | 323 } |
| 381 | 324 |
| 382 - (void)dealloc { | 325 - (void)dealloc { |
| 383 [self browserWillBeDestroyed]; | 326 [self browserWillBeDestroyed]; |
| 384 [super dealloc]; | 327 [super dealloc]; |
| 385 } | 328 } |
| 386 | 329 |
| 387 - (void)browserWillBeDestroyed { | 330 - (void)browserWillBeDestroyed { |
| 388 [overflowMenu_ setDelegate:nil]; | |
| 389 // Explicitly destroy the ToolbarActionsBar so all buttons get removed with a | 331 // Explicitly destroy the ToolbarActionsBar so all buttons get removed with a |
| 390 // valid BrowserActionsController, and so we can verify state before | 332 // valid BrowserActionsController, and so we can verify state before |
| 391 // destruction. | 333 // destruction. |
| 392 if (toolbarActionsBar_.get()) { | 334 if (toolbarActionsBar_.get()) { |
| 393 toolbarActionsBar_->DeleteActions(); | 335 toolbarActionsBar_->DeleteActions(); |
| 394 toolbarActionsBar_.reset(); | 336 toolbarActionsBar_.reset(); |
| 395 } | 337 } |
| 396 DCHECK_EQ(0u, [buttons_ count]); | 338 DCHECK_EQ(0u, [buttons_ count]); |
| 397 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 339 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 398 browser_ = nullptr; | 340 browser_ = nullptr; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 418 } | 360 } |
| 419 | 361 |
| 420 - (NSPoint)popupPointForId:(const std::string&)id { | 362 - (NSPoint)popupPointForId:(const std::string&)id { |
| 421 BrowserActionButton* button = [self buttonForId:id]; | 363 BrowserActionButton* button = [self buttonForId:id]; |
| 422 if (!button) | 364 if (!button) |
| 423 return NSZeroPoint; | 365 return NSZeroPoint; |
| 424 | 366 |
| 425 NSRect bounds; | 367 NSRect bounds; |
| 426 NSView* referenceButton = button; | 368 NSView* referenceButton = button; |
| 427 if ([button superview] != containerView_ || isOverflow_) { | 369 if ([button superview] != containerView_ || isOverflow_) { |
| 428 referenceButton = toolbarActionsBar_->platform_settings().chevron_enabled ? | 370 bounds = [[[self toolbarController] appMenuButton] bounds]; |
| 429 chevronMenuButton_.get() : [[self toolbarController] appMenuButton]; | |
| 430 bounds = [referenceButton bounds]; | |
| 431 } else { | 371 } else { |
| 432 bounds = [button convertRect:[button frameAfterAnimation] | 372 bounds = [button convertRect:[button frameAfterAnimation] |
| 433 fromView:[button superview]]; | 373 fromView:[button superview]]; |
| 434 } | 374 } |
| 435 | 375 |
| 436 return [self popupPointForView:referenceButton withBounds:bounds]; | 376 return [self popupPointForView:referenceButton withBounds:bounds]; |
| 437 } | 377 } |
| 438 | 378 |
| 439 - (BOOL)chevronIsHidden { | |
| 440 if (!chevronMenuButton_.get()) | |
| 441 return YES; | |
| 442 | |
| 443 if (![chevronAnimation_ isAnimating]) | |
| 444 return [chevronMenuButton_ isHidden]; | |
| 445 | |
| 446 DCHECK([[chevronAnimation_ viewAnimations] count] > 0); | |
| 447 | |
| 448 // The chevron is animating in or out. Determine which one and have the return | |
| 449 // value reflect where the animation is headed. | |
| 450 NSString* effect = [[[chevronAnimation_ viewAnimations] objectAtIndex:0] | |
| 451 valueForKey:NSViewAnimationEffectKey]; | |
| 452 if (effect == NSViewAnimationFadeInEffect) { | |
| 453 return NO; | |
| 454 } else if (effect == NSViewAnimationFadeOutEffect) { | |
| 455 return YES; | |
| 456 } | |
| 457 | |
| 458 NOTREACHED(); | |
| 459 return YES; | |
| 460 } | |
| 461 | |
| 462 - (content::WebContents*)currentWebContents { | 379 - (content::WebContents*)currentWebContents { |
| 463 return browser_->tab_strip_model()->GetActiveWebContents(); | 380 return browser_->tab_strip_model()->GetActiveWebContents(); |
| 464 } | 381 } |
| 465 | 382 |
| 466 - (BrowserActionButton*)mainButtonForId:(const std::string&)id { | 383 - (BrowserActionButton*)mainButtonForId:(const std::string&)id { |
| 467 BrowserActionsController* mainController = isOverflow_ ? | 384 BrowserActionsController* mainController = isOverflow_ ? |
| 468 [[self toolbarController] browserActionsController] : self; | 385 [[self toolbarController] browserActionsController] : self; |
| 469 return [mainController buttonForId:id]; | 386 return [mainController buttonForId:id]; |
| 470 } | 387 } |
| 471 | 388 |
| 472 - (ToolbarActionsBar*)toolbarActionsBar { | 389 - (ToolbarActionsBar*)toolbarActionsBar { |
| 473 return toolbarActionsBar_.get(); | 390 return toolbarActionsBar_.get(); |
| 474 } | 391 } |
| 475 | 392 |
| 476 - (void)setFocusedInOverflow:(BOOL)focused { | 393 - (void)setFocusedInOverflow:(BOOL)focused { |
| 477 BOOL isFocused = focusedViewIndex_ != -1; | 394 BOOL isFocused = focusedViewIndex_ != -1; |
| 478 if (isFocused != focused) { | 395 if (isFocused != focused) { |
| 479 int index = focused ? | 396 int index = focused ? |
| 480 [buttons_ count] - toolbarActionsBar_->GetIconCount() : -1; | 397 [buttons_ count] - toolbarActionsBar_->GetIconCount() : -1; |
| 481 [self setFocusedViewIndex:index]; | 398 [self setFocusedViewIndex:index]; |
| 482 } | 399 } |
| 483 } | 400 } |
| 484 | 401 |
| 485 - (gfx::Size)sizeForOverflowWidth:(int)maxWidth { | 402 - (gfx::Size)sizeForOverflowWidth:(int)maxWidth { |
| 486 toolbarActionsBar_->SetOverflowRowWidth(maxWidth); | 403 toolbarActionsBar_->SetOverflowRowWidth(maxWidth); |
| 487 return [self preferredSize]; | 404 return [self preferredSize]; |
| 488 } | 405 } |
| 489 | 406 |
| 490 #pragma mark - | |
| 491 #pragma mark NSMenuDelegate | |
| 492 | |
| 493 - (void)menuNeedsUpdate:(NSMenu*)menu { | |
| 494 [menu removeAllItems]; | |
| 495 | |
| 496 // See menu_button.h for documentation on why this is needed. | |
| 497 [menu addItemWithTitle:@"" action:nil keyEquivalent:@""]; | |
| 498 | |
| 499 NSUInteger iconCount = toolbarActionsBar_->GetIconCount(); | |
| 500 NSRange hiddenButtonRange = | |
| 501 NSMakeRange(iconCount, [buttons_ count] - iconCount); | |
| 502 for (BrowserActionButton* button in | |
| 503 [buttons_ subarrayWithRange:hiddenButtonRange]) { | |
| 504 NSString* name = | |
| 505 base::SysUTF16ToNSString([button viewController]->GetActionName()); | |
| 506 NSMenuItem* item = | |
| 507 [menu addItemWithTitle:name | |
| 508 action:@selector(chevronItemSelected:) | |
| 509 keyEquivalent:@""]; | |
| 510 [item setRepresentedObject:button]; | |
| 511 [item setImage:[button compositedImage]]; | |
| 512 [item setTarget:self]; | |
| 513 [item setEnabled:[button isEnabled]]; | |
| 514 } | |
| 515 } | |
| 516 | |
| 517 #pragma mark - | |
| 518 #pragma mark Private Methods | |
| 519 | |
| 520 - (void)addViewForAction:(ToolbarActionViewController*)action | 407 - (void)addViewForAction:(ToolbarActionViewController*)action |
| 521 withIndex:(NSUInteger)index { | 408 withIndex:(NSUInteger)index { |
| 522 NSRect buttonFrame = NSMakeRect(NSMaxX([containerView_ bounds]), | 409 NSRect buttonFrame = NSMakeRect(NSMaxX([containerView_ bounds]), |
| 523 0, | 410 0, |
| 524 ToolbarActionsBar::IconWidth(false), | 411 ToolbarActionsBar::IconWidth(false), |
| 525 ToolbarActionsBar::IconHeight()); | 412 ToolbarActionsBar::IconHeight()); |
| 526 BrowserActionButton* newButton = | 413 BrowserActionButton* newButton = |
| 527 [[[BrowserActionButton alloc] | 414 [[[BrowserActionButton alloc] |
| 528 initWithFrame:buttonFrame | 415 initWithFrame:buttonFrame |
| 529 viewController:action | 416 viewController:action |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 ToolbarActionViewController* other_controller = | 455 ToolbarActionViewController* other_controller = |
| 569 [[self buttonAtIndex:j] viewController]; | 456 [[self buttonAtIndex:j] viewController]; |
| 570 if (other_controller == toolbar_actions[i]) | 457 if (other_controller == toolbar_actions[i]) |
| 571 break; | 458 break; |
| 572 ++j; | 459 ++j; |
| 573 } | 460 } |
| 574 [buttons_ exchangeObjectAtIndex:i withObjectAtIndex:j]; | 461 [buttons_ exchangeObjectAtIndex:i withObjectAtIndex:j]; |
| 575 } | 462 } |
| 576 } | 463 } |
| 577 | 464 |
| 578 [self showChevronIfNecessaryInFrame:[containerView_ frame]]; | |
| 579 NSUInteger startIndex = toolbarActionsBar_->GetStartIndexInBounds(); | 465 NSUInteger startIndex = toolbarActionsBar_->GetStartIndexInBounds(); |
| 580 NSUInteger endIndex = toolbarActionsBar_->GetEndIndexInBounds(); | 466 NSUInteger endIndex = toolbarActionsBar_->GetEndIndexInBounds(); |
| 581 for (NSUInteger i = 0; i < [buttons_ count]; ++i) { | 467 for (NSUInteger i = 0; i < [buttons_ count]; ++i) { |
| 582 BrowserActionButton* button = [buttons_ objectAtIndex:i]; | 468 BrowserActionButton* button = [buttons_ objectAtIndex:i]; |
| 583 if ([button isBeingDragged]) | 469 if ([button isBeingDragged]) |
| 584 continue; | 470 continue; |
| 585 | 471 |
| 586 [self moveButton:[buttons_ objectAtIndex:i] toIndex:i]; | 472 [self moveButton:[buttons_ objectAtIndex:i] toIndex:i]; |
| 587 | 473 |
| 588 if (i >= startIndex && i < endIndex) { | 474 if (i >= startIndex && i < endIndex) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 // Cocoa goes a little crazy if we try and change animations while adjusting | 521 // Cocoa goes a little crazy if we try and change animations while adjusting |
| 636 // child frames (i.e., the buttons). If the toolbar is already animating, | 522 // child frames (i.e., the buttons). If the toolbar is already animating, |
| 637 // just jump to the new frame. (This typically only happens if someone is | 523 // just jump to the new frame. (This typically only happens if someone is |
| 638 // "spamming" a button to add/remove an action.) If the window isn't visible | 524 // "spamming" a button to add/remove an action.) If the window isn't visible |
| 639 // (for example it's in the process of being created), don't bother animating. | 525 // (for example it's in the process of being created), don't bother animating. |
| 640 BOOL animate = !toolbarActionsBar_->suppress_animation() && | 526 BOOL animate = !toolbarActionsBar_->suppress_animation() && |
| 641 ![containerView_ isAnimating] && [[containerView_ window] isVisible]; | 527 ![containerView_ isAnimating] && [[containerView_ window] isVisible]; |
| 642 [self updateContainerVisibility]; | 528 [self updateContainerVisibility]; |
| 643 [containerView_ resizeToWidth:width | 529 [containerView_ resizeToWidth:width |
| 644 animate:animate]; | 530 animate:animate]; |
| 645 NSRect frame = animate ? [containerView_ animationEndFrame] : | |
| 646 [containerView_ frame]; | |
| 647 | |
| 648 [self showChevronIfNecessaryInFrame:frame]; | |
| 649 | |
| 650 [containerView_ setNeedsDisplay:YES]; | 531 [containerView_ setNeedsDisplay:YES]; |
| 651 | 532 |
| 652 if (!animate) { | 533 if (!animate) { |
| 653 [[NSNotificationCenter defaultCenter] | 534 [[NSNotificationCenter defaultCenter] |
| 654 postNotificationName:kBrowserActionVisibilityChangedNotification | 535 postNotificationName:kBrowserActionVisibilityChangedNotification |
| 655 object:self]; | 536 object:self]; |
| 656 } | 537 } |
| 657 [self redraw]; | 538 [self redraw]; |
| 658 [self updateGrippyCursors]; | 539 [self updateGrippyCursors]; |
| 659 } | 540 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 } | 599 } |
| 719 | 600 |
| 720 - (BrowserActionButton*)buttonAtIndex:(NSUInteger)index { | 601 - (BrowserActionButton*)buttonAtIndex:(NSUInteger)index { |
| 721 return static_cast<BrowserActionButton*>([buttons_ objectAtIndex:index]); | 602 return static_cast<BrowserActionButton*>([buttons_ objectAtIndex:index]); |
| 722 } | 603 } |
| 723 | 604 |
| 724 - (void)containerFrameChanged:(NSNotification*)notification { | 605 - (void)containerFrameChanged:(NSNotification*)notification { |
| 725 [self updateButtonPositions]; | 606 [self updateButtonPositions]; |
| 726 [self updateButtonOpacity]; | 607 [self updateButtonOpacity]; |
| 727 [[containerView_ window] invalidateCursorRectsForView:containerView_]; | 608 [[containerView_ window] invalidateCursorRectsForView:containerView_]; |
| 728 [self updateChevronPositionInFrame:[containerView_ frame]]; | |
| 729 } | 609 } |
| 730 | 610 |
| 731 - (void)containerDragStart:(NSNotification*)notification { | 611 - (void)containerDragStart:(NSNotification*)notification { |
| 732 [self setChevronHidden:YES inFrame:[containerView_ frame]]; | |
| 733 for (BrowserActionButton* button in buttons_.get()) { | 612 for (BrowserActionButton* button in buttons_.get()) { |
| 734 if ([button superview] != containerView_) { | 613 if ([button superview] != containerView_) { |
| 735 [button setAlphaValue:1.0]; | 614 [button setAlphaValue:1.0]; |
| 736 [containerView_ addSubview:button]; | 615 [containerView_ addSubview:button]; |
| 737 } | 616 } |
| 738 } | 617 } |
| 739 } | 618 } |
| 740 | 619 |
| 741 - (void)containerDragFinished:(NSNotification*)notification { | 620 - (void)containerDragFinished:(NSNotification*)notification { |
| 742 for (BrowserActionButton* button in buttons_.get()) { | 621 for (BrowserActionButton* button in buttons_.get()) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 [focusedButton performClick:focusedButton]; | 671 [focusedButton performClick:focusedButton]; |
| 793 } | 672 } |
| 794 break; | 673 break; |
| 795 } | 674 } |
| 796 case BROWSER_ACTIONS_INVALID_KEY_ACTION: | 675 case BROWSER_ACTIONS_INVALID_KEY_ACTION: |
| 797 NOTREACHED(); | 676 NOTREACHED(); |
| 798 } | 677 } |
| 799 } | 678 } |
| 800 | 679 |
| 801 - (void)actionButtonDragging:(NSNotification*)notification { | 680 - (void)actionButtonDragging:(NSNotification*)notification { |
| 802 suppressChevron_ = YES; | |
| 803 if (![self chevronIsHidden]) | |
| 804 [self setChevronHidden:YES inFrame:[containerView_ frame]]; | |
| 805 | |
| 806 // Determine what index the dragged button should lie in, alter the model and | 681 // Determine what index the dragged button should lie in, alter the model and |
| 807 // reposition the buttons. | 682 // reposition the buttons. |
| 808 BrowserActionButton* draggedButton = [notification object]; | 683 BrowserActionButton* draggedButton = [notification object]; |
| 809 NSRect draggedButtonFrame = [draggedButton frame]; | 684 NSRect draggedButtonFrame = [draggedButton frame]; |
| 810 // Find the mid-point. We flip the y-coordinates so that y = 0 is at the | 685 // Find the mid-point. We flip the y-coordinates so that y = 0 is at the |
| 811 // top of the container to make row calculation more logical. | 686 // top of the container to make row calculation more logical. |
| 812 NSPoint midPoint = | 687 NSPoint midPoint = |
| 813 NSMakePoint(NSMidX(draggedButtonFrame), | 688 NSMakePoint(NSMidX(draggedButtonFrame), |
| 814 NSMaxY([containerView_ bounds]) - NSMidY(draggedButtonFrame)); | 689 NSMaxY([containerView_ bounds]) - NSMidY(draggedButtonFrame)); |
| 815 | 690 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 829 [buttons_ count] - toolbarActionsBar_->GetIconCount() : 0; | 704 [buttons_ count] - toolbarActionsBar_->GetIconCount() : 0; |
| 830 NSInteger index = | 705 NSInteger index = |
| 831 std::min(maxIndex, offset + rowIndex * icons_per_row + indexInRow); | 706 std::min(maxIndex, offset + rowIndex * icons_per_row + indexInRow); |
| 832 | 707 |
| 833 toolbarActionsBar_->OnDragDrop([buttons_ indexOfObject:draggedButton], | 708 toolbarActionsBar_->OnDragDrop([buttons_ indexOfObject:draggedButton], |
| 834 index, | 709 index, |
| 835 ToolbarActionsBar::DRAG_TO_SAME); | 710 ToolbarActionsBar::DRAG_TO_SAME); |
| 836 } | 711 } |
| 837 | 712 |
| 838 - (void)actionButtonDragFinished:(NSNotification*)notification { | 713 - (void)actionButtonDragFinished:(NSNotification*)notification { |
| 839 suppressChevron_ = NO; | |
| 840 [self redraw]; | 714 [self redraw]; |
| 841 } | 715 } |
| 842 | 716 |
| 843 - (NSRect)frameForIndex:(NSUInteger)index { | 717 - (NSRect)frameForIndex:(NSUInteger)index { |
| 844 gfx::Rect frameRect = toolbarActionsBar_->GetFrameForIndex(index); | 718 gfx::Rect frameRect = toolbarActionsBar_->GetFrameForIndex(index); |
| 845 int iconWidth = ToolbarActionsBar::IconWidth(false); | 719 int iconWidth = ToolbarActionsBar::IconWidth(false); |
| 846 // The toolbar actions bar will return an empty rect if the index is for an | 720 // The toolbar actions bar will return an empty rect if the index is for an |
| 847 // action that is before range we show (i.e., is for a button that's on the | 721 // action that is before range we show (i.e., is for a button that's on the |
| 848 // main bar, and this is the overflow). Set the frame to be outside the bounds | 722 // main bar, and this is the overflow). Set the frame to be outside the bounds |
| 849 // of the view. | 723 // of the view. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 if (!NSEqualRects(buttonFrame, [button frameAfterAnimation])) { | 775 if (!NSEqualRects(buttonFrame, [button frameAfterAnimation])) { |
| 902 [button setFrame:buttonFrame | 776 [button setFrame:buttonFrame |
| 903 animate:!toolbarActionsBar_->suppress_animation() && !isOverflow_]; | 777 animate:!toolbarActionsBar_->suppress_animation() && !isOverflow_]; |
| 904 } | 778 } |
| 905 } | 779 } |
| 906 | 780 |
| 907 - (BOOL)browserActionClicked:(BrowserActionButton*)button { | 781 - (BOOL)browserActionClicked:(BrowserActionButton*)button { |
| 908 return [button viewController]->ExecuteAction(true); | 782 return [button viewController]->ExecuteAction(true); |
| 909 } | 783 } |
| 910 | 784 |
| 911 - (void)showChevronIfNecessaryInFrame:(NSRect)frame { | |
| 912 if (!toolbarActionsBar_->platform_settings().chevron_enabled) | |
| 913 return; | |
| 914 bool hidden = suppressChevron_ || | |
| 915 toolbarActionsBar_->GetIconCount() == [self buttonCount]; | |
| 916 [self setChevronHidden:hidden inFrame:frame]; | |
| 917 } | |
| 918 | |
| 919 - (void)updateChevronPositionInFrame:(NSRect)frame { | |
| 920 CGFloat xPos = NSWidth(frame) - kChevronWidth - | |
| 921 toolbarActionsBar_->platform_settings().item_spacing; | |
| 922 NSRect buttonFrame = NSMakeRect(xPos, | |
| 923 0, | |
| 924 kChevronWidth, | |
| 925 ToolbarActionsBar::IconHeight()); | |
| 926 [chevronAnimation_ stopAnimation]; | |
| 927 [chevronMenuButton_ setFrame:buttonFrame]; | |
| 928 } | |
| 929 | |
| 930 - (void)setChevronHidden:(BOOL)hidden | |
| 931 inFrame:(NSRect)frame { | |
| 932 if (!toolbarActionsBar_->platform_settings().chevron_enabled || | |
| 933 hidden == [self chevronIsHidden]) | |
| 934 return; | |
| 935 | |
| 936 if (!chevronMenuButton_.get()) { | |
| 937 bool isModeMaterial = ui::MaterialDesignController::IsModeMaterial(); | |
| 938 if (isModeMaterial) { | |
| 939 chevronMenuButton_.reset([[ChevronMenuButton alloc] init]); | |
| 940 } else { | |
| 941 chevronMenuButton_.reset([[MenuButton alloc] init]); | |
| 942 } | |
| 943 [chevronMenuButton_ setOpenMenuOnClick:YES]; | |
| 944 [chevronMenuButton_ setBordered:NO]; | |
| 945 [chevronMenuButton_ setShowsBorderOnlyWhileMouseInside:YES]; | |
| 946 | |
| 947 if (!isModeMaterial) { | |
| 948 [[chevronMenuButton_ cell] setImageID:IDR_BROWSER_ACTIONS_OVERFLOW | |
| 949 forButtonState:image_button_cell::kDefaultState]; | |
| 950 [[chevronMenuButton_ cell] setImageID:IDR_BROWSER_ACTIONS_OVERFLOW_H | |
| 951 forButtonState:image_button_cell::kHoverState]; | |
| 952 [[chevronMenuButton_ cell] setImageID:IDR_BROWSER_ACTIONS_OVERFLOW_P | |
| 953 forButtonState:image_button_cell::kPressedState]; | |
| 954 } | |
| 955 overflowMenu_.reset([[NSMenu alloc] initWithTitle:@""]); | |
| 956 [overflowMenu_ setAutoenablesItems:NO]; | |
| 957 [overflowMenu_ setDelegate:self]; | |
| 958 [chevronMenuButton_ setAttachedMenu:overflowMenu_]; | |
| 959 | |
| 960 [containerView_ addSubview:chevronMenuButton_]; | |
| 961 } | |
| 962 | |
| 963 [self updateChevronPositionInFrame:frame]; | |
| 964 | |
| 965 // Stop any running animation. | |
| 966 [chevronAnimation_ stopAnimation]; | |
| 967 | |
| 968 if (toolbarActionsBar_->suppress_animation()) { | |
| 969 [chevronMenuButton_ setHidden:hidden]; | |
| 970 return; | |
| 971 } | |
| 972 | |
| 973 NSString* animationEffect; | |
| 974 if (hidden) { | |
| 975 animationEffect = NSViewAnimationFadeOutEffect; | |
| 976 } else { | |
| 977 [chevronMenuButton_ setHidden:NO]; | |
| 978 animationEffect = NSViewAnimationFadeInEffect; | |
| 979 } | |
| 980 NSDictionary* animationDictionary = @{ | |
| 981 NSViewAnimationTargetKey : chevronMenuButton_.get(), | |
| 982 NSViewAnimationEffectKey : animationEffect | |
| 983 }; | |
| 984 [chevronAnimation_ setViewAnimations: | |
| 985 [NSArray arrayWithObject:animationDictionary]]; | |
| 986 [chevronAnimation_ startAnimation]; | |
| 987 } | |
| 988 | |
| 989 - (void)chevronItemSelected:(id)menuItem { | |
| 990 [self browserActionClicked:[menuItem representedObject]]; | |
| 991 } | |
| 992 | |
| 993 - (void)updateGrippyCursors { | 785 - (void)updateGrippyCursors { |
| 994 [containerView_ | 786 [containerView_ |
| 995 setCanDragLeft:toolbarActionsBar_->GetIconCount() != [buttons_ count]]; | 787 setCanDragLeft:toolbarActionsBar_->GetIconCount() != [buttons_ count]]; |
| 996 [containerView_ setCanDragRight:[self visibleButtonCount] > 0]; | 788 [containerView_ setCanDragRight:[self visibleButtonCount] > 0]; |
| 997 [[containerView_ window] invalidateCursorRectsForView:containerView_]; | 789 [[containerView_ window] invalidateCursorRectsForView:containerView_]; |
| 998 } | 790 } |
| 999 | 791 |
| 1000 - (ToolbarController*)toolbarController { | 792 - (ToolbarController*)toolbarController { |
| 1001 return [[BrowserWindowController browserWindowControllerForWindow: | 793 return [[BrowserWindowController browserWindowControllerForWindow: |
| 1002 browser_->window()->GetNativeWindow()] toolbarController]; | 794 browser_->window()->GetNativeWindow()] toolbarController]; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1048 } | 840 } |
| 1049 | 841 |
| 1050 #pragma mark - | 842 #pragma mark - |
| 1051 #pragma mark Testing Methods | 843 #pragma mark Testing Methods |
| 1052 | 844 |
| 1053 - (BrowserActionButton*)buttonWithIndex:(NSUInteger)index { | 845 - (BrowserActionButton*)buttonWithIndex:(NSUInteger)index { |
| 1054 return index < [buttons_ count] ? [buttons_ objectAtIndex:index] : nil; | 846 return index < [buttons_ count] ? [buttons_ objectAtIndex:index] : nil; |
| 1055 } | 847 } |
| 1056 | 848 |
| 1057 @end | 849 @end |
| OLD | NEW |