OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "browser_actions_controller.h" | 5 #import "browser_actions_controller.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "app/resource_bundle.h" | 10 #include "app/resource_bundle.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 - (void)createActionButtonForExtension:(Extension*)extension | 56 - (void)createActionButtonForExtension:(Extension*)extension |
57 withIndex:(NSUInteger)index; | 57 withIndex:(NSUInteger)index; |
58 | 58 |
59 // Removes an action button for the given extension from the container. This | 59 // Removes an action button for the given extension from the container. This |
60 // method also does not affect the underlying toolbar model since it is called | 60 // method also does not affect the underlying toolbar model since it is called |
61 // when the toolbar model changes. | 61 // when the toolbar model changes. |
62 - (void)removeActionButtonForExtension:(Extension*)extension; | 62 - (void)removeActionButtonForExtension:(Extension*)extension; |
63 | 63 |
64 // Useful in the case of a Browser Action being added/removed from the middle of | 64 // Useful in the case of a Browser Action being added/removed from the middle of |
65 // the container, this method repositions each button according to the current | 65 // the container, this method repositions each button according to the current |
66 // toolbar model. | 66 // toolbar model. Since during an insert or remove, the icons to the right will |
67 - (void)repositionActionButtonsAndAnimate:(BOOL)animate; | 67 // be the only ones needing a position change, a starting point is provided. |
| 68 - (void)repositionActionButtonsStartingAtIndex:(NSUInteger)index |
| 69 animate:(BOOL)animate; |
68 | 70 |
69 // During container resizing, buttons become more transparent as they are pushed | 71 // During container resizing, buttons become more transparent as they are pushed |
70 // off the screen. This method updates each button's opacity determined by the | 72 // off the screen. This method updates each button's opacity determined by the |
71 // position of the button. | 73 // position of the button. |
72 - (void)updateButtonOpacity; | 74 - (void)updateButtonOpacity; |
73 | 75 |
74 // Returns the existing button with the given extension backing it; nil if it | 76 // Returns the existing button with the given extension backing it; nil if it |
75 // cannot be found or the extension's ID is invalid. | 77 // cannot be found or the extension's ID is invalid. |
76 - (BrowserActionButton*)buttonForExtension:(Extension*)extension; | 78 - (BrowserActionButton*)buttonForExtension:(Extension*)extension; |
77 | 79 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 break; | 183 break; |
182 } | 184 } |
183 default: | 185 default: |
184 NOTREACHED() << L"Unexpected notification"; | 186 NOTREACHED() << L"Unexpected notification"; |
185 } | 187 } |
186 } | 188 } |
187 | 189 |
188 // ExtensionToolbarModel::Observer implementation. | 190 // ExtensionToolbarModel::Observer implementation. |
189 void BrowserActionAdded(Extension* extension, int index) { | 191 void BrowserActionAdded(Extension* extension, int index) { |
190 [owner_ createActionButtonForExtension:extension withIndex:index]; | 192 [owner_ createActionButtonForExtension:extension withIndex:index]; |
191 [owner_ resizeContainerAndAnimate:NO]; | |
192 } | 193 } |
193 | 194 |
194 void BrowserActionRemoved(Extension* extension) { | 195 void BrowserActionRemoved(Extension* extension) { |
195 [owner_ removeActionButtonForExtension:extension]; | 196 [owner_ removeActionButtonForExtension:extension]; |
196 [owner_ resizeContainerAndAnimate:NO]; | |
197 } | 197 } |
198 | 198 |
199 private: | 199 private: |
200 // The object we need to inform when we get a notification. Weak. Owns us. | 200 // The object we need to inform when we get a notification. Weak. Owns us. |
201 BrowserActionsController* owner_; | 201 BrowserActionsController* owner_; |
202 | 202 |
203 // Used for registering to receive notifications and automatic clean up. | 203 // Used for registering to receive notifications and automatic clean up. |
204 NotificationRegistrar registrar_; | 204 NotificationRegistrar registrar_; |
205 | 205 |
206 DISALLOW_COPY_AND_ASSIGN(ExtensionsServiceObserverBridge); | 206 DISALLOW_COPY_AND_ASSIGN(ExtensionsServiceObserverBridge); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 chevronAnimation_.reset([[NSViewAnimation alloc] init]); | 266 chevronAnimation_.reset([[NSViewAnimation alloc] init]); |
267 [chevronAnimation_ gtm_setDuration:kAnimationDuration | 267 [chevronAnimation_ gtm_setDuration:kAnimationDuration |
268 eventMask:NSLeftMouseDownMask]; | 268 eventMask:NSLeftMouseDownMask]; |
269 [chevronAnimation_ setAnimationBlockingMode:NSAnimationNonblocking]; | 269 [chevronAnimation_ setAnimationBlockingMode:NSAnimationNonblocking]; |
270 | 270 |
271 hiddenButtons_.reset([[NSMutableArray alloc] init]); | 271 hiddenButtons_.reset([[NSMutableArray alloc] init]); |
272 buttons_.reset([[NSMutableDictionary alloc] init]); | 272 buttons_.reset([[NSMutableDictionary alloc] init]); |
273 [self createButtons]; | 273 [self createButtons]; |
274 [self showChevronIfNecessaryInFrame:[containerView_ frame] animate:NO]; | 274 [self showChevronIfNecessaryInFrame:[containerView_ frame] animate:NO]; |
275 [self updateGrippyCursors]; | 275 [self updateGrippyCursors]; |
| 276 isInitialized_ = YES; |
276 } | 277 } |
277 | 278 |
278 return self; | 279 return self; |
279 } | 280 } |
280 | 281 |
281 - (void)dealloc { | 282 - (void)dealloc { |
282 if (toolbarModel_) | 283 if (toolbarModel_) |
283 toolbarModel_->RemoveObserver(observer_.get()); | 284 toolbarModel_->RemoveObserver(observer_.get()); |
284 | 285 |
285 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 286 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
(...skipping 24 matching lines...) Expand all Loading... |
310 if (iconCount < 0) // If no buttons are hidden. | 311 if (iconCount < 0) // If no buttons are hidden. |
311 iconCount = [self buttonCount]; | 312 iconCount = [self buttonCount]; |
312 | 313 |
313 [containerView_ resizeToWidth:[self containerWidthWithButtonCount:iconCount] | 314 [containerView_ resizeToWidth:[self containerWidthWithButtonCount:iconCount] |
314 animate:animate]; | 315 animate:animate]; |
315 NSRect frame = animate ? [containerView_ animationEndFrame] : | 316 NSRect frame = animate ? [containerView_ animationEndFrame] : |
316 [containerView_ frame]; | 317 [containerView_ frame]; |
317 | 318 |
318 [self showChevronIfNecessaryInFrame:frame animate:animate]; | 319 [self showChevronIfNecessaryInFrame:frame animate:animate]; |
319 | 320 |
320 if (!animate) { | 321 [[NSNotificationCenter defaultCenter] |
321 [[NSNotificationCenter defaultCenter] | 322 postNotificationName:kBrowserActionVisibilityChangedNotification |
322 postNotificationName:kBrowserActionVisibilityChangedNotification | 323 object:self]; |
323 object:self]; | |
324 } | |
325 } | 324 } |
326 | 325 |
327 - (NSView*)browserActionViewForExtension:(Extension*)extension { | 326 - (NSView*)browserActionViewForExtension:(Extension*)extension { |
328 for (BrowserActionButton* button in [buttons_ allValues]) { | 327 for (BrowserActionButton* button in [buttons_ allValues]) { |
329 if ([button extension] == extension) | 328 if ([button extension] == extension) |
330 return button; | 329 return button; |
331 } | 330 } |
332 NOTREACHED(); | 331 NOTREACHED(); |
333 return nil; | 332 return nil; |
334 } | 333 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 tabId:[self currentTabId]] autorelease]; | 453 tabId:[self currentTabId]] autorelease]; |
455 [newButton setTarget:self]; | 454 [newButton setTarget:self]; |
456 [newButton setAction:@selector(browserActionClicked:)]; | 455 [newButton setAction:@selector(browserActionClicked:)]; |
457 NSString* buttonKey = base::SysUTF8ToNSString(extension->id()); | 456 NSString* buttonKey = base::SysUTF8ToNSString(extension->id()); |
458 if (!buttonKey) | 457 if (!buttonKey) |
459 return; | 458 return; |
460 | 459 |
461 [buttons_ setObject:newButton forKey:buttonKey]; | 460 [buttons_ setObject:newButton forKey:buttonKey]; |
462 if (index < [self containerButtonCapacity]) { | 461 if (index < [self containerButtonCapacity]) { |
463 [containerView_ addSubview:newButton]; | 462 [containerView_ addSubview:newButton]; |
| 463 if (!profile_->IsOffTheRecord() && isInitialized_) |
| 464 toolbarModel_->SetVisibleIconCount([self visibleButtonCount]); |
464 } else { | 465 } else { |
465 [hiddenButtons_ addObject:newButton]; | 466 [hiddenButtons_ addObject:newButton]; |
466 [newButton setAlphaValue:0.0]; | 467 [newButton setAlphaValue:0.0]; |
467 [self updateOverflowMenu]; | 468 [self updateOverflowMenu]; |
468 } | 469 } |
469 | 470 |
470 [[NSNotificationCenter defaultCenter] | 471 [[NSNotificationCenter defaultCenter] |
471 addObserver:self | 472 addObserver:self |
472 selector:@selector(actionButtonDragging:) | 473 selector:@selector(actionButtonDragging:) |
473 name:kBrowserActionButtonDraggingNotification | 474 name:kBrowserActionButtonDraggingNotification |
474 object:newButton]; | 475 object:newButton]; |
475 | 476 |
476 [self repositionActionButtonsAndAnimate:NO]; | |
477 [containerView_ setMaxWidth: | 477 [containerView_ setMaxWidth: |
478 [self containerWidthWithButtonCount:[self buttonCount]]]; | 478 [self containerWidthWithButtonCount:[self buttonCount]]]; |
479 [containerView_ setNeedsDisplay:YES]; | 479 [self resizeContainerAndAnimate:isInitialized_]; |
| 480 |
| 481 // TODO(andybons): Use isInitialized_ to animate this. |
| 482 [self repositionActionButtonsStartingAtIndex:0 animate:NO]; |
480 } | 483 } |
481 | 484 |
482 - (void)removeActionButtonForExtension:(Extension*)extension { | 485 - (void)removeActionButtonForExtension:(Extension*)extension { |
483 if (!extension->browser_action()) | 486 if (!extension->browser_action()) |
484 return; | 487 return; |
485 | 488 |
486 NSString* buttonKey = base::SysUTF8ToNSString(extension->id()); | 489 NSString* buttonKey = base::SysUTF8ToNSString(extension->id()); |
487 if (!buttonKey) | 490 if (!buttonKey) |
488 return; | 491 return; |
489 | 492 |
490 BrowserActionButton* button = [buttons_ objectForKey:buttonKey]; | 493 BrowserActionButton* button = [buttons_ objectForKey:buttonKey]; |
| 494 [buttons_ removeObjectForKey:buttonKey]; |
491 // This could be the case in incognito, where only a subset of extensions are | 495 // This could be the case in incognito, where only a subset of extensions are |
492 // shown. | 496 // shown. |
493 if (!button) | 497 if (!button) |
494 return; | 498 return; |
495 | 499 |
496 [button removeFromSuperview]; | 500 [button removeFromSuperview]; |
497 // It may or may not be hidden, but it won't matter to NSMutableArray either | |
498 // way. | |
499 [hiddenButtons_ removeObject:button]; | |
500 [self updateOverflowMenu]; | |
501 | 501 |
502 [buttons_ removeObjectForKey:buttonKey]; | 502 if ([hiddenButtons_ containsObject:button]) { |
| 503 [hiddenButtons_ removeObject:button]; |
| 504 [self updateOverflowMenu]; |
| 505 } else { |
| 506 if (!profile_->IsOffTheRecord() && isInitialized_) |
| 507 toolbarModel_->SetVisibleIconCount([self visibleButtonCount]); |
| 508 } |
| 509 |
503 if ([self buttonCount] == 0) { | 510 if ([self buttonCount] == 0) { |
504 // No more buttons? Hide the container. | 511 // No more buttons? Hide the container. |
505 [containerView_ setHidden:YES]; | 512 [containerView_ setHidden:YES]; |
506 } else { | 513 } else { |
507 [self repositionActionButtonsAndAnimate:NO]; | 514 [self repositionActionButtonsStartingAtIndex:0 animate:NO]; |
508 } | 515 } |
509 [containerView_ setMaxWidth: | 516 [containerView_ setMaxWidth: |
510 [self containerWidthWithButtonCount:[self buttonCount]]]; | 517 [self containerWidthWithButtonCount:[self buttonCount]]]; |
511 [containerView_ setNeedsDisplay:YES]; | 518 [self resizeContainerAndAnimate:isInitialized_]; |
512 } | 519 } |
513 | 520 |
514 - (void)repositionActionButtonsAndAnimate:(BOOL)animate { | 521 - (void)repositionActionButtonsStartingAtIndex:(NSUInteger)index |
| 522 animate:(BOOL)animate { |
515 NSUInteger i = 0; | 523 NSUInteger i = 0; |
516 for (ExtensionList::iterator iter = toolbarModel_->begin(); | 524 for (ExtensionList::iterator iter = toolbarModel_->begin(); |
517 iter != toolbarModel_->end(); ++iter) { | 525 iter != toolbarModel_->end(); ++iter) { |
518 if (![self shouldDisplayBrowserAction:*iter]) | 526 if (![self shouldDisplayBrowserAction:*iter]) |
519 continue; | 527 continue; |
| 528 |
| 529 if (i < index) { |
| 530 ++i; |
| 531 continue; |
| 532 } |
520 BrowserActionButton* button = [self buttonForExtension:(*iter)]; | 533 BrowserActionButton* button = [self buttonForExtension:(*iter)]; |
521 if (!button) | 534 if (!button) |
522 continue; | 535 continue; |
523 if (![button isBeingDragged]) | 536 if (![button isBeingDragged]) |
524 [self moveButton:button toIndex:i animate:animate]; | 537 [self moveButton:button toIndex:i animate:animate]; |
525 ++i; | 538 ++i; |
526 } | 539 } |
527 } | 540 } |
528 | 541 |
529 - (void)updateButtonOpacity { | 542 - (void)updateButtonOpacity { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 NSUInteger index = 0; | 663 NSUInteger index = 0; |
651 for (ExtensionList::iterator iter = toolbarModel_->begin(); | 664 for (ExtensionList::iterator iter = toolbarModel_->begin(); |
652 iter != toolbarModel_->end(); ++iter) { | 665 iter != toolbarModel_->end(); ++iter) { |
653 BrowserActionButton* button = [self buttonForExtension:(*iter)]; | 666 BrowserActionButton* button = [self buttonForExtension:(*iter)]; |
654 CGFloat intersectionWidth = | 667 CGFloat intersectionWidth = |
655 NSWidth(NSIntersectionRect(draggedButtonFrame, [button frame])); | 668 NSWidth(NSIntersectionRect(draggedButtonFrame, [button frame])); |
656 | 669 |
657 if (intersectionWidth > dragThreshold && button != draggedButton && | 670 if (intersectionWidth > dragThreshold && button != draggedButton && |
658 ![button isAnimating] && index < [self visibleButtonCount]) { | 671 ![button isAnimating] && index < [self visibleButtonCount]) { |
659 toolbarModel_->MoveBrowserAction([draggedButton extension], index); | 672 toolbarModel_->MoveBrowserAction([draggedButton extension], index); |
660 [self repositionActionButtonsAndAnimate:YES]; | 673 [self repositionActionButtonsStartingAtIndex:0 animate:YES]; |
661 return; | 674 return; |
662 } | 675 } |
663 ++index; | 676 ++index; |
664 } | 677 } |
665 } | 678 } |
666 | 679 |
667 - (void)actionButtonDragFinished:(NSNotification*)notification { | 680 - (void)actionButtonDragFinished:(NSNotification*)notification { |
668 [self showChevronIfNecessaryInFrame:[containerView_ frame] animate:YES]; | 681 [self showChevronIfNecessaryInFrame:[containerView_ frame] animate:YES]; |
669 [self repositionActionButtonsAndAnimate:YES]; | 682 [self repositionActionButtonsStartingAtIndex:0 animate:YES]; |
670 } | 683 } |
671 | 684 |
672 - (void)moveButton:(BrowserActionButton*)button | 685 - (void)moveButton:(BrowserActionButton*)button |
673 toIndex:(NSUInteger)index | 686 toIndex:(NSUInteger)index |
674 animate:(BOOL)animate { | 687 animate:(BOOL)animate { |
675 CGFloat xOffset = kGrippyXOffset + | 688 CGFloat xOffset = kGrippyXOffset + |
676 (index * (kBrowserActionWidth + kBrowserActionButtonPadding)); | 689 (index * (kBrowserActionWidth + kBrowserActionButtonPadding)); |
677 NSRect buttonFrame = [button frame]; | 690 NSRect buttonFrame = [button frame]; |
678 buttonFrame.origin.x = xOffset; | 691 buttonFrame.origin.x = xOffset; |
679 [button setFrame:buttonFrame animate:animate]; | 692 [button setFrame:buttonFrame animate:animate]; |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 iter != toolbarModel_->end(); ++iter) { | 833 iter != toolbarModel_->end(); ++iter) { |
821 if (i == index) | 834 if (i == index) |
822 return [buttons_ objectForKey:base::SysUTF8ToNSString((*iter)->id())]; | 835 return [buttons_ objectForKey:base::SysUTF8ToNSString((*iter)->id())]; |
823 | 836 |
824 ++i; | 837 ++i; |
825 } | 838 } |
826 return nil; | 839 return nil; |
827 } | 840 } |
828 | 841 |
829 @end | 842 @end |
OLD | NEW |