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 3 // found in the LICENSE file. 4 5 #import "chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.h" 6 7 #include "base/logging.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/strings/sys_string_conversions.h" 10 #import "chrome/browser/ui/cocoa/menu_button.h" 11 #include "chrome/browser/ui/toolbar/back_forward_menu_model.h" 12 #import "ui/base/cocoa/cocoa_event_utils.h" 13 #include "ui/gfx/image/image.h" 14 15 using base::SysUTF16ToNSString; 16 17 @implementation BackForwardMenuController 18 19 // Accessors and mutators: 20 21 @synthesize type = type_; 22 23 // Own methods: 24 25 - (id)initWithBrowser:(Browser*)browser 26 modelType:(BackForwardMenuType)type 27 button:(MenuButton*)button { 28 if ((self = [super init])) { 29 type_ = type; 30 button_ = button; 31 model_.reset(new BackForwardMenuModel(browser, type_)); 32 DCHECK(model_.get()); 33 backForwardMenu_.reset([[NSMenu alloc] initWithTitle:@""]); 34 DCHECK(backForwardMenu_.get()); 35 [backForwardMenu_ setDelegate:self]; 36 37 [button_ setAttachedMenu:backForwardMenu_]; 38 [button_ setOpenMenuOnClick:NO]; 39 } 40 return self; 41 } 42 43 // Methods as delegate: 44 45 // Called by backForwardMenu_ just before tracking begins. 46 //TODO(viettrungluu): should we do anything for chapter stops (see model)? 47 - (void)menuNeedsUpdate:(NSMenu*)menu { 48 DCHECK(menu == backForwardMenu_); 49 50 // Remove old menu items (backwards order is as good as any). 51 for (NSInteger i = [menu numberOfItems]; i > 0; i--) 52 [menu removeItemAtIndex:(i - 1)]; 53 54 // 0-th item must be blank. (This is because we use a pulldown list, for which 55 // Cocoa uses the 0-th item as "title" in the button.) 56 [menu insertItemWithTitle:@"" 57 action:nil 58 keyEquivalent:@"" 59 atIndex:0]; 60 for (int menuID = 0; menuID < model_->GetItemCount(); menuID++) { 61 if (model_->IsSeparator(menuID)) { 62 [menu insertItem:[NSMenuItem separatorItem] 63 atIndex:(menuID + 1)]; 64 } else { 65 // Create a menu item with the right label. 66 NSMenuItem* menuItem = [[NSMenuItem alloc] 67 initWithTitle:SysUTF16ToNSString(model_->GetLabelAt(menuID)) 68 action:nil 69 keyEquivalent:@""]; 70 [menuItem autorelease]; 71 72 gfx::Image icon; 73 // Icon (if it has one). 74 if (model_->GetIconAt(menuID, &icon)) 75 [menuItem setImage:icon.ToNSImage()]; 76 77 // This will make it call our |-executeMenuItem:| method. We store the 78 // |menuID| (or |menu_id|) in the tag. 79 [menuItem setTag:menuID]; 80 [menuItem setTarget:self]; 81 [menuItem setAction:@selector(executeMenuItem:)]; 82 83 // Put it in the menu! 84 [menu insertItem:menuItem 85 atIndex:(menuID + 1)]; 86 } 87 } 88 } 89 90 // Action methods: 91 92 - (void)executeMenuItem:(id)sender { 93 DCHECK([sender isKindOfClass:[NSMenuItem class]]); 94 int menuID = [sender tag]; 95 int event_flags = ui::EventFlagsFromNSEvent([NSApp currentEvent]); 96 model_->ActivatedAt(menuID, event_flags); 97 } 98 99 @end // @implementation BackForwardMenuController 100