| 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 |