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

Unified 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/cocoa/menu_controller.mm
===================================================================
--- chrome/browser/cocoa/menu_controller.mm (revision 0)
+++ chrome/browser/cocoa/menu_controller.mm (revision 0)
@@ -0,0 +1,145 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#import "chrome/browser/cocoa/menu_controller.h"
+
+#include "app/l10n_util_mac.h"
+#include "app/menus/simple_menu_model.h"
+#include "base/logging.h"
+#include "base/sys_string_conversions.h"
+
+@interface MenuController(Private)
+- (NSMenu*)menuFromModel:(menus::MenuModel*)model;
+- (void)addSeparatorToMenu:(NSMenu*)menu
+ atIndex:(int)index;
+- (void)addItemToMenu:(NSMenu*)menu
+ atIndex:(int)index
+ fromModel:(menus::MenuModel*)model
+ modelIndex:(int)modelIndex;
+@end
+
+@implementation MenuController
+
+- (id)initWithModel:(menus::MenuModel*)model
+ useWithPopUpButtonCell:(BOOL)useWithCell {
+ if ((self = [super init])) {
+ menu_.reset([[self menuFromModel:model] retain]);
+ // If this is to be used with a NSPopUpButtonCell, add an item at the 0th
+ // position that's empty. Doing it after the menu has been constructed won't
+ // complicate creation logic, and since the tags are model indexes, they
+ // are unaffected by the extra item.
+ if (useWithCell) {
+ scoped_nsobject<NSMenuItem> blankItem(
+ [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]);
+ [menu_ insertItem:blankItem atIndex:0];
+ }
+ }
+ return self;
+}
+
+// Creates a NSMenu from the given model. If the model has submenus, this can
+// be invoked recursively.
+- (NSMenu*)menuFromModel:(menus::MenuModel*)model {
+ NSMenu* menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
+
+ // The indices may not always start at zero (the windows system menu is one
+ // example where this is used) so just make sure we can handle it.
+ // SimpleMenuModel currently always starts at 0.
+ int firstItemIndex = model->GetFirstItemIndex(menu);
+ DCHECK(firstItemIndex == 0);
+ const int count = model->GetItemCount();
+ for (int index = firstItemIndex; index < firstItemIndex + count; index++) {
+ int modelIndex = index - firstItemIndex;
+ if (model->GetTypeAt(modelIndex) == menus::MenuModel::TYPE_SEPARATOR) {
+ [self addSeparatorToMenu:menu atIndex:index];
+ } else {
+ [self addItemToMenu:menu atIndex:index fromModel:model
+ modelIndex:modelIndex];
+ }
+ }
+
+ return menu;
+}
+
+// Adds a separator item at the given index. As the separator doesn't need
+// anything from the model, this method doesn't need the model index as the
+// other method below does.
+- (void)addSeparatorToMenu:(NSMenu*)menu
+ atIndex:(int)index {
+ NSMenuItem* separator = [NSMenuItem separatorItem];
+ [menu insertItem:separator atIndex:index];
+}
+
+// Adds an item or a hierarchical menu to the item at the |index|,
+// associated with the entry in the model indentifed by |modelIndex|.
+- (void)addItemToMenu:(NSMenu*)menu
+ atIndex:(int)index
+ fromModel:(menus::MenuModel*)model
+ modelIndex:(int)modelIndex {
+ NSString* label =
+ l10n_util::FixUpWindowsStyleLabel(model->GetLabelAt(modelIndex));
+ scoped_nsobject<NSMenuItem> item(
+ [[NSMenuItem alloc] initWithTitle:label
+ action:@selector(itemSelected:)
+ keyEquivalent:@""]);
+ menus::MenuModel::ItemType type = model->GetTypeAt(modelIndex);
+ if (type == menus::MenuModel::TYPE_SUBMENU) {
+ // Recursively build a submenu from the sub-model at this index.
+ [item setTarget:nil];
+ [item setAction:nil];
+ menus::MenuModel* submenuModel = model->GetSubmenuModelAt(modelIndex);
+ NSMenu* submenu =
+ [self menuFromModel:(menus::SimpleMenuModel*)submenuModel];
+ [item setSubmenu:submenu];
+ } else {
+ // The MenuModel works on indexes so we can't just set the command id as the
+ // tag like we do in other menus. Also set the represented object to be
+ // the model so hierarchical menus check the correct index in the correct
+ // model.
+ [item setTag:modelIndex];
+ [item setTarget:self];
+ NSValue* modelObject = [NSValue valueWithPointer:model];
+ [item setRepresentedObject:modelObject]; // Retains |modelObject|.
+ }
+ [menu insertItem:item atIndex:index];
+}
+
+// Called before the menu is to be displayed to update the state (enabled,
+// radio, etc) of each item in the menu.
+- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
+ SEL action = [item action];
+ if (action != @selector(itemSelected:))
+ return NO;
+
+ NSInteger modelIndex = [item tag];
+ menus::MenuModel* model =
+ static_cast<menus::MenuModel*>(
+ [[(id)item representedObject] pointerValue]);
+ DCHECK(model);
+ if (model) {
+ BOOL checked = model->IsItemCheckedAt(modelIndex);
+ DCHECK([(id)item isKindOfClass:[NSMenuItem class]]);
+ [(id)item setState:(checked ? NSOnState : NSOffState)];
+ return model->IsEnabledAt(modelIndex);
+ }
+ return NO;
+}
+
+// Called when the user chooses a particular menu item. |sender| is the menu
+// item chosen.
+- (void)itemSelected:(id)sender {
+ NSInteger modelIndex = [sender tag];
+ menus::MenuModel* model =
+ static_cast<menus::MenuModel*>(
+ [[sender representedObject] pointerValue]);
+ DCHECK(model);
+ if (model);
+ model->ActivatedAt(modelIndex);
+}
+
+- (NSMenu*)menu {
+ return menu_.get();
+}
+
+@end
Property changes on: chrome/browser/cocoa/menu_controller.mm
___________________________________________________________________
Name: svn:eol-style
+ LF
« 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