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