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

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

Issue 10797054: Use NSMenuDelegate for browser action overflow menu to update it upon opening. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rsesek Created 8 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/cocoa/extensions/browser_actions_controller.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "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 "base/sys_string_conversions.h" 10 #include "base/sys_string_conversions.h"
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 - (void)containerDragStart:(NSNotification*)notification; 114 - (void)containerDragStart:(NSNotification*)notification;
115 115
116 // Sends a notification for the toolbar to reposition surrounding UI elements. 116 // Sends a notification for the toolbar to reposition surrounding UI elements.
117 - (void)containerDragging:(NSNotification*)notification; 117 - (void)containerDragging:(NSNotification*)notification;
118 118
119 // Determines which buttons need to be hidden based on the new size, hides them 119 // Determines which buttons need to be hidden based on the new size, hides them
120 // and updates the chevron overflow menu. Also fires a notification to let the 120 // and updates the chevron overflow menu. Also fires a notification to let the
121 // toolbar know that the drag has finished. 121 // toolbar know that the drag has finished.
122 - (void)containerDragFinished:(NSNotification*)notification; 122 - (void)containerDragFinished:(NSNotification*)notification;
123 123
124 // Updates the image associated with the button should it be within the chevron
125 // menu.
126 - (void)actionButtonUpdated:(NSNotification*)notification;
127
128 // Adjusts the position of the surrounding action buttons depending on where the 124 // Adjusts the position of the surrounding action buttons depending on where the
129 // button is within the container. 125 // button is within the container.
130 - (void)actionButtonDragging:(NSNotification*)notification; 126 - (void)actionButtonDragging:(NSNotification*)notification;
131 127
132 // Updates the position of the Browser Actions within the container. This fires 128 // Updates the position of the Browser Actions within the container. This fires
133 // when _any_ Browser Action button is done dragging to keep all open windows in 129 // when _any_ Browser Action button is done dragging to keep all open windows in
134 // sync visually. 130 // sync visually.
135 - (void)actionButtonDragFinished:(NSNotification*)notification; 131 - (void)actionButtonDragFinished:(NSNotification*)notification;
136 132
137 // Moves the given button both visually and within the toolbar model to the 133 // Moves the given button both visually and within the toolbar model to the
(...skipping 22 matching lines...) Expand all
160 - (void)updateChevronPositionInFrame:(NSRect)frame; 156 - (void)updateChevronPositionInFrame:(NSRect)frame;
161 157
162 // Shows or hides the chevron, animating as specified by |animate|. 158 // Shows or hides the chevron, animating as specified by |animate|.
163 - (void)setChevronHidden:(BOOL)hidden 159 - (void)setChevronHidden:(BOOL)hidden
164 inFrame:(NSRect)frame 160 inFrame:(NSRect)frame
165 animate:(BOOL)animate; 161 animate:(BOOL)animate;
166 162
167 // Handles when a menu item within the chevron overflow menu is selected. 163 // Handles when a menu item within the chevron overflow menu is selected.
168 - (void)chevronItemSelected:(id)menuItem; 164 - (void)chevronItemSelected:(id)menuItem;
169 165
170 // Clears and then populates the overflow menu based on the contents of
171 // |hiddenButtons_|.
172 - (void)updateOverflowMenu;
173
174 // Updates the container's grippy cursor based on the number of hidden buttons. 166 // Updates the container's grippy cursor based on the number of hidden buttons.
175 - (void)updateGrippyCursors; 167 - (void)updateGrippyCursors;
176 168
177 // Returns the ID of the currently selected tab or -1 if none exists. 169 // Returns the ID of the currently selected tab or -1 if none exists.
178 - (int)currentTabId; 170 - (int)currentTabId;
179 @end 171 @end
180 172
181 // A helper class to proxy extension notifications to the view controller's 173 // A helper class to proxy extension notifications to the view controller's
182 // appropriate methods. 174 // appropriate methods.
183 class ExtensionServiceObserverBridge : public content::NotificationObserver, 175 class ExtensionServiceObserverBridge : public content::NotificationObserver,
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 return YES; 408 return YES;
417 } 409 }
418 410
419 + (void)registerUserPrefs:(PrefService*)prefs { 411 + (void)registerUserPrefs:(PrefService*)prefs {
420 prefs->RegisterDoublePref(prefs::kBrowserActionContainerWidth, 412 prefs->RegisterDoublePref(prefs::kBrowserActionContainerWidth,
421 0, 413 0,
422 PrefService::UNSYNCABLE_PREF); 414 PrefService::UNSYNCABLE_PREF);
423 } 415 }
424 416
425 #pragma mark - 417 #pragma mark -
418 #pragma mark NSMenuDelegate
419
420 - (void)menuNeedsUpdate:(NSMenu*)menu {
421 [menu removeAllItems];
422
423 // See menu_button.h for documentation on why this is needed.
424 [menu addItemWithTitle:@"" action:nil keyEquivalent:@""];
425
426 for (BrowserActionButton* button in hiddenButtons_.get()) {
427 NSString* name = base::SysUTF8ToNSString([button extension]->name());
428 NSMenuItem* item =
429 [menu addItemWithTitle:name
430 action:@selector(chevronItemSelected:)
431 keyEquivalent:@""];
432 [item setRepresentedObject:button];
433 [item setImage:[button compositedImage]];
434 [item setTarget:self];
435 [item setEnabled:[button isEnabled]];
436 }
437 }
438
439 #pragma mark -
426 #pragma mark Private Methods 440 #pragma mark Private Methods
427 441
428 - (void)createButtons { 442 - (void)createButtons {
429 if (!toolbarModel_) 443 if (!toolbarModel_)
430 return; 444 return;
431 445
432 NSUInteger i = 0; 446 NSUInteger i = 0;
433 for (ExtensionList::iterator iter = toolbarModel_->begin(); 447 for (ExtensionList::iterator iter = toolbarModel_->begin();
434 iter != toolbarModel_->end(); ++iter) { 448 iter != toolbarModel_->end(); ++iter) {
435 if (![self shouldDisplayBrowserAction:*iter]) 449 if (![self shouldDisplayBrowserAction:*iter])
436 continue; 450 continue;
437 451
438 [self createActionButtonForExtension:*iter withIndex:i++]; 452 [self createActionButtonForExtension:*iter withIndex:i++];
439 } 453 }
440 454
441 [[NSNotificationCenter defaultCenter]
442 addObserver:self
443 selector:@selector(actionButtonUpdated:)
444 name:kBrowserActionButtonUpdatedNotification
445 object:nil];
446
447 CGFloat width = [self savedWidth]; 455 CGFloat width = [self savedWidth];
448 [containerView_ resizeToWidth:width animate:NO]; 456 [containerView_ resizeToWidth:width animate:NO];
449 } 457 }
450 458
451 - (void)createActionButtonForExtension:(const Extension*)extension 459 - (void)createActionButtonForExtension:(const Extension*)extension
452 withIndex:(NSUInteger)index { 460 withIndex:(NSUInteger)index {
453 if (!extension->browser_action()) 461 if (!extension->browser_action())
454 return; 462 return;
455 463
456 if (![self shouldDisplayBrowserAction:extension]) 464 if (![self shouldDisplayBrowserAction:extension])
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 BrowserActionButton* button = [buttons_ objectForKey:buttonKey]; 512 BrowserActionButton* button = [buttons_ objectForKey:buttonKey];
505 // This could be the case in incognito, where only a subset of extensions are 513 // This could be the case in incognito, where only a subset of extensions are
506 // shown. 514 // shown.
507 if (!button) 515 if (!button)
508 return; 516 return;
509 517
510 [button removeFromSuperview]; 518 [button removeFromSuperview];
511 // It may or may not be hidden, but it won't matter to NSMutableArray either 519 // It may or may not be hidden, but it won't matter to NSMutableArray either
512 // way. 520 // way.
513 [hiddenButtons_ removeObject:button]; 521 [hiddenButtons_ removeObject:button];
514 [self updateOverflowMenu];
515 522
516 [buttons_ removeObjectForKey:buttonKey]; 523 [buttons_ removeObjectForKey:buttonKey];
517 if ([self buttonCount] == 0) { 524 if ([self buttonCount] == 0) {
518 // No more buttons? Hide the container. 525 // No more buttons? Hide the container.
519 [containerView_ setHidden:YES]; 526 [containerView_ setHidden:YES];
520 } else { 527 } else {
521 [self positionActionButtonsAndAnimate:NO]; 528 [self positionActionButtonsAndAnimate:NO];
522 } 529 }
523 [containerView_ setMaxWidth: 530 [containerView_ setMaxWidth:
524 [self containerWidthWithButtonCount:[self buttonCount]]]; 531 [self containerWidthWithButtonCount:[self buttonCount]]];
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 NSWidth(NSIntersectionRect([containerView_ bounds], buttonFrame)); 636 NSWidth(NSIntersectionRect([containerView_ bounds], buttonFrame));
630 // Pad the threshold by 5 pixels in order to have the buttons hide more 637 // Pad the threshold by 5 pixels in order to have the buttons hide more
631 // easily. 638 // easily.
632 if (([containerView_ grippyPinned] && intersectionWidth > 0) || 639 if (([containerView_ grippyPinned] && intersectionWidth > 0) ||
633 (intersectionWidth <= (NSWidth(buttonFrame) / 2) + 5.0)) { 640 (intersectionWidth <= (NSWidth(buttonFrame) / 2) + 5.0)) {
634 [button setAlphaValue:0.0]; 641 [button setAlphaValue:0.0];
635 [button removeFromSuperview]; 642 [button removeFromSuperview];
636 [hiddenButtons_ addObject:button]; 643 [hiddenButtons_ addObject:button];
637 } 644 }
638 } 645 }
639 [self updateOverflowMenu];
640 [self updateGrippyCursors]; 646 [self updateGrippyCursors];
641 647
642 if (!profile_->IsOffTheRecord()) 648 if (!profile_->IsOffTheRecord())
643 toolbarModel_->SetVisibleIconCount([self visibleButtonCount]); 649 toolbarModel_->SetVisibleIconCount([self visibleButtonCount]);
644 650
645 [[NSNotificationCenter defaultCenter] 651 [[NSNotificationCenter defaultCenter]
646 postNotificationName:kBrowserActionGrippyDragFinishedNotification 652 postNotificationName:kBrowserActionGrippyDragFinishedNotification
647 object:self]; 653 object:self];
648 } 654 }
649 655
650 - (void)actionButtonUpdated:(NSNotification*)notification {
651 BrowserActionButton* button = [notification object];
652 if (![hiddenButtons_ containsObject:button])
653 return;
654
655 // +1 item because of the title placeholder. See |updateOverflowMenu|.
656 NSUInteger menuIndex = [hiddenButtons_ indexOfObject:button] + 1;
657 NSMenuItem* item = [[chevronMenuButton_ attachedMenu] itemAtIndex:menuIndex];
658 DCHECK(button == [item representedObject]);
659 [item setImage:[button compositedImage]];
660 }
661
662 - (void)actionButtonDragging:(NSNotification*)notification { 656 - (void)actionButtonDragging:(NSNotification*)notification {
663 if (![self chevronIsHidden]) 657 if (![self chevronIsHidden])
664 [self setChevronHidden:YES inFrame:[containerView_ frame] animate:YES]; 658 [self setChevronHidden:YES inFrame:[containerView_ frame] animate:YES];
665 659
666 // Determine what index the dragged button should lie in, alter the model and 660 // Determine what index the dragged button should lie in, alter the model and
667 // reposition the buttons. 661 // reposition the buttons.
668 CGFloat dragThreshold = std::floor(kBrowserActionWidth / 2); 662 CGFloat dragThreshold = std::floor(kBrowserActionWidth / 2);
669 BrowserActionButton* draggedButton = [notification object]; 663 BrowserActionButton* draggedButton = [notification object];
670 NSRect draggedButtonFrame = [draggedButton frame]; 664 NSRect draggedButtonFrame = [draggedButton frame];
671 665
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 // Make sure the button is within the visible container. 698 // Make sure the button is within the visible container.
705 if ([button superview] != containerView_) { 699 if ([button superview] != containerView_) {
706 [containerView_ addSubview:button]; 700 [containerView_ addSubview:button];
707 [button setAlphaValue:1.0]; 701 [button setAlphaValue:1.0];
708 [hiddenButtons_ removeObjectIdenticalTo:button]; 702 [hiddenButtons_ removeObjectIdenticalTo:button];
709 } 703 }
710 } else if (![hiddenButtons_ containsObject:button]) { 704 } else if (![hiddenButtons_ containsObject:button]) {
711 [hiddenButtons_ addObject:button]; 705 [hiddenButtons_ addObject:button];
712 [button removeFromSuperview]; 706 [button removeFromSuperview];
713 [button setAlphaValue:0.0]; 707 [button setAlphaValue:0.0];
714 [self updateOverflowMenu];
715 } 708 }
716 } 709 }
717 710
718 - (void)browserActionClicked:(BrowserActionButton*)button { 711 - (void)browserActionClicked:(BrowserActionButton*)button {
719 const Extension* extension = [button extension]; 712 const Extension* extension = [button extension];
720 GURL popupUrl; 713 GURL popupUrl;
721 switch (toolbarModel_->ExecuteBrowserAction(extension, browser_, &popupUrl)) { 714 switch (toolbarModel_->ExecuteBrowserAction(extension, browser_, &popupUrl)) {
722 case ExtensionToolbarModel::ACTION_NONE: 715 case ExtensionToolbarModel::ACTION_NONE:
723 break; 716 break;
724 case ExtensionToolbarModel::ACTION_SHOW_POPUP: { 717 case ExtensionToolbarModel::ACTION_SHOW_POPUP: {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 [chevronMenuButton_ setBordered:NO]; 760 [chevronMenuButton_ setBordered:NO];
768 [chevronMenuButton_ setShowsBorderOnlyWhileMouseInside:YES]; 761 [chevronMenuButton_ setShowsBorderOnlyWhileMouseInside:YES];
769 762
770 [[chevronMenuButton_ cell] setImageID:IDR_BROWSER_ACTIONS_OVERFLOW 763 [[chevronMenuButton_ cell] setImageID:IDR_BROWSER_ACTIONS_OVERFLOW
771 forButtonState:image_button_cell::kDefaultState]; 764 forButtonState:image_button_cell::kDefaultState];
772 [[chevronMenuButton_ cell] setImageID:IDR_BROWSER_ACTIONS_OVERFLOW_H 765 [[chevronMenuButton_ cell] setImageID:IDR_BROWSER_ACTIONS_OVERFLOW_H
773 forButtonState:image_button_cell::kHoverState]; 766 forButtonState:image_button_cell::kHoverState];
774 [[chevronMenuButton_ cell] setImageID:IDR_BROWSER_ACTIONS_OVERFLOW_P 767 [[chevronMenuButton_ cell] setImageID:IDR_BROWSER_ACTIONS_OVERFLOW_P
775 forButtonState:image_button_cell::kPressedState]; 768 forButtonState:image_button_cell::kPressedState];
776 769
770 overflowMenu_.reset([[NSMenu alloc] initWithTitle:@""]);
771 [overflowMenu_ setAutoenablesItems:NO];
772 [overflowMenu_ setDelegate:self];
773 [chevronMenuButton_ setAttachedMenu:overflowMenu_];
774
777 [containerView_ addSubview:chevronMenuButton_]; 775 [containerView_ addSubview:chevronMenuButton_];
778 } 776 }
779 777
780 if (!hidden)
781 [self updateOverflowMenu];
782
783 [self updateChevronPositionInFrame:frame]; 778 [self updateChevronPositionInFrame:frame];
784 779
785 // Stop any running animation. 780 // Stop any running animation.
786 [chevronAnimation_ stopAnimation]; 781 [chevronAnimation_ stopAnimation];
787 782
788 if (!animate) { 783 if (!animate) {
789 [chevronMenuButton_ setHidden:hidden]; 784 [chevronMenuButton_ setHidden:hidden];
790 return; 785 return;
791 } 786 }
792 787
(...skipping 12 matching lines...) Expand all
805 } 800 }
806 [chevronAnimation_ setViewAnimations: 801 [chevronAnimation_ setViewAnimations:
807 [NSArray arrayWithObject:animationDictionary]]; 802 [NSArray arrayWithObject:animationDictionary]];
808 [chevronAnimation_ startAnimation]; 803 [chevronAnimation_ startAnimation];
809 } 804 }
810 805
811 - (void)chevronItemSelected:(id)menuItem { 806 - (void)chevronItemSelected:(id)menuItem {
812 [self browserActionClicked:[menuItem representedObject]]; 807 [self browserActionClicked:[menuItem representedObject]];
813 } 808 }
814 809
815 // TODO(yoz): This only gets called when the set of actions in the overflow
816 // menu changes (not for things that would update page actions).
817 // It should instead be called each time the menu is opened.
818 - (void)updateOverflowMenu {
819 overflowMenu_.reset([[NSMenu alloc] initWithTitle:@""]);
820 // See menu_button.h for documentation on why this is needed.
821 [overflowMenu_ addItemWithTitle:@"" action:nil keyEquivalent:@""];
822 [overflowMenu_ setAutoenablesItems:NO];
823
824 for (BrowserActionButton* button in hiddenButtons_.get()) {
825 NSString* name = base::SysUTF8ToNSString([button extension]->name());
826 NSMenuItem* item =
827 [overflowMenu_ addItemWithTitle:name
828 action:@selector(chevronItemSelected:)
829 keyEquivalent:@""];
830 [item setRepresentedObject:button];
831 [item setImage:[button compositedImage]];
832 [item setTarget:self];
833 [item setEnabled:[button isEnabled]];
834 }
835 [chevronMenuButton_ setAttachedMenu:overflowMenu_];
836 }
837
838 - (void)updateGrippyCursors { 810 - (void)updateGrippyCursors {
839 [containerView_ setCanDragLeft:[hiddenButtons_ count] > 0]; 811 [containerView_ setCanDragLeft:[hiddenButtons_ count] > 0];
840 [containerView_ setCanDragRight:[self visibleButtonCount] > 0]; 812 [containerView_ setCanDragRight:[self visibleButtonCount] > 0];
841 [[containerView_ window] invalidateCursorRectsForView:containerView_]; 813 [[containerView_ window] invalidateCursorRectsForView:containerView_];
842 } 814 }
843 815
844 - (int)currentTabId { 816 - (int)currentTabId {
845 TabContents* selected_tab = chrome::GetActiveTabContents(browser_); 817 TabContents* selected_tab = chrome::GetActiveTabContents(browser_);
846 if (!selected_tab) 818 if (!selected_tab)
847 return -1; 819 return -1;
848 820
849 return selected_tab->restore_tab_helper()->session_id().id(); 821 return selected_tab->restore_tab_helper()->session_id().id();
850 } 822 }
851 823
852 #pragma mark - 824 #pragma mark -
853 #pragma mark Testing Methods 825 #pragma mark Testing Methods
854 826
855 - (NSButton*)buttonWithIndex:(NSUInteger)index { 827 - (NSButton*)buttonWithIndex:(NSUInteger)index {
856 if (profile_->IsOffTheRecord()) 828 if (profile_->IsOffTheRecord())
857 index = toolbarModel_->IncognitoIndexToOriginal(index); 829 index = toolbarModel_->IncognitoIndexToOriginal(index);
858 if (index < toolbarModel_->size()) { 830 if (index < toolbarModel_->size()) {
859 const Extension* extension = toolbarModel_->GetExtensionByIndex(index); 831 const Extension* extension = toolbarModel_->GetExtensionByIndex(index);
860 return [buttons_ objectForKey:base::SysUTF8ToNSString(extension->id())]; 832 return [buttons_ objectForKey:base::SysUTF8ToNSString(extension->id())];
861 } 833 }
862 return nil; 834 return nil;
863 } 835 }
864 836
865 @end 837 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/extensions/browser_actions_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698