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

Side by Side Diff: chrome/browser/cocoa/menu_controller.mm

Issue 465130: Share the code that builds the page menu in a common model, make Mac and Win ... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years 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
Property Changes:
Name: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file.
4
5 #import "chrome/browser/cocoa/menu_controller.h"
6
7 #include "app/l10n_util_mac.h"
8 #include "app/menus/simple_menu_model.h"
9 #include "base/logging.h"
10 #include "base/sys_string_conversions.h"
11
12 @interface MenuController(Private)
13 - (NSMenu*)menuFromModel:(menus::MenuModel*)model;
14 - (void)addSeparatorToMenu:(NSMenu*)menu
15 atIndex:(int)index;
16 - (void)addItemToMenu:(NSMenu*)menu
17 atIndex:(int)index
18 fromModel:(menus::MenuModel*)model
19 modelIndex:(int)modelIndex;
20 @end
21
22 @implementation MenuController
23
24 - (id)initWithModel:(menus::MenuModel*)model
25 useWithPopUpButtonCell:(BOOL)useWithCell {
26 if ((self = [super init])) {
27 menu_.reset([[self menuFromModel:model] retain]);
28 // If this is to be used with a NSPopUpButtonCell, add an item at the 0th
29 // position that's empty. Doing it after the menu has been constructed won't
30 // complicate creation logic, and since the tags are model indexes, they
31 // are unaffected by the extra item.
32 if (useWithCell) {
33 scoped_nsobject<NSMenuItem> blankItem(
34 [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]);
35 [menu_ insertItem:blankItem atIndex:0];
36 }
37 }
38 return self;
39 }
40
41 // Creates a NSMenu from the given model. If the model has submenus, this can
42 // be invoked recursively.
43 - (NSMenu*)menuFromModel:(menus::MenuModel*)model {
44 NSMenu* menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
45
46 // The indices may not always start at zero (the windows system menu is one
47 // example where this is used) so just make sure we can handle it.
48 // SimpleMenuModel currently always starts at 0.
49 int firstItemIndex = model->GetFirstItemIndex(menu);
50 DCHECK(firstItemIndex == 0);
51 const int count = model->GetItemCount();
52 for (int index = firstItemIndex; index < firstItemIndex + count; index++) {
53 int modelIndex = index - firstItemIndex;
54 if (model->GetTypeAt(modelIndex) == menus::MenuModel::TYPE_SEPARATOR) {
55 [self addSeparatorToMenu:menu atIndex:index];
56 } else {
57 [self addItemToMenu:menu atIndex:index fromModel:model
58 modelIndex:modelIndex];
59 }
60 }
61
62 return menu;
63 }
64
65 // Adds a separator item at the given index. As the separator doesn't need
66 // anything from the model, this method doesn't need the model index as the
67 // other method below does.
68 - (void)addSeparatorToMenu:(NSMenu*)menu
69 atIndex:(int)index {
70 NSMenuItem* separator = [NSMenuItem separatorItem];
71 [menu insertItem:separator atIndex:index];
72 }
73
74 // Adds an item or a hierarchical menu to the item at the |index|,
75 // associated with the entry in the model indentifed by |modelIndex|.
76 - (void)addItemToMenu:(NSMenu*)menu
77 atIndex:(int)index
78 fromModel:(menus::MenuModel*)model
79 modelIndex:(int)modelIndex {
80 NSString* label =
81 l10n_util::FixUpWindowsStyleLabel(model->GetLabelAt(modelIndex));
82 scoped_nsobject<NSMenuItem> item(
83 [[NSMenuItem alloc] initWithTitle:label
84 action:@selector(itemSelected:)
85 keyEquivalent:@""]);
86 menus::MenuModel::ItemType type = model->GetTypeAt(modelIndex);
87 if (type == menus::MenuModel::TYPE_SUBMENU) {
88 // Recursively build a submenu from the sub-model at this index.
89 [item setTarget:nil];
90 [item setAction:nil];
91 menus::MenuModel* submenuModel = model->GetSubmenuModelAt(modelIndex);
92 NSMenu* submenu =
93 [self menuFromModel:(menus::SimpleMenuModel*)submenuModel];
94 [item setSubmenu:submenu];
95 } else {
96 // The MenuModel works on indexes so we can't just set the command id as the
97 // tag like we do in other menus. Also set the represented object to be
98 // the model so hierarchical menus check the correct index in the correct
99 // model.
100 [item setTag:modelIndex];
101 [item setTarget:self];
102 NSValue* modelObject = [NSValue valueWithPointer:model];
103 [item setRepresentedObject:modelObject]; // Retains |modelObject|.
104 }
105 [menu insertItem:item atIndex:index];
106 }
107
108 // Called before the menu is to be displayed to update the state (enabled,
109 // radio, etc) of each item in the menu.
110 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
111 SEL action = [item action];
112 if (action != @selector(itemSelected:))
113 return NO;
114
115 NSInteger modelIndex = [item tag];
116 menus::MenuModel* model =
117 static_cast<menus::MenuModel*>(
118 [[(id)item representedObject] pointerValue]);
119 DCHECK(model);
120 if (model) {
121 BOOL checked = model->IsItemCheckedAt(modelIndex);
122 DCHECK([(id)item isKindOfClass:[NSMenuItem class]]);
123 [(id)item setState:(checked ? NSOnState : NSOffState)];
124 return model->IsEnabledAt(modelIndex);
125 }
126 return NO;
127 }
128
129 // Called when the user chooses a particular menu item. |sender| is the menu
130 // item chosen.
131 - (void)itemSelected:(id)sender {
132 NSInteger modelIndex = [sender tag];
133 menus::MenuModel* model =
134 static_cast<menus::MenuModel*>(
135 [[sender representedObject] pointerValue]);
136 DCHECK(model);
137 if (model);
138 model->ActivatedAt(modelIndex);
139 }
140
141 - (NSMenu*)menu {
142 return menu_.get();
143 }
144
145 @end
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/menu_controller.h ('k') | chrome/browser/cocoa/menu_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698