diff options
Diffstat (limited to 'chrome/browser/cocoa/wrench_menu_controller.mm')
-rw-r--r-- | chrome/browser/cocoa/wrench_menu_controller.mm | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/wrench_menu_controller.mm b/chrome/browser/cocoa/wrench_menu_controller.mm new file mode 100644 index 0000000..0f31548 --- /dev/null +++ b/chrome/browser/cocoa/wrench_menu_controller.mm @@ -0,0 +1,127 @@ +// Copyright (c) 2010 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/wrench_menu_controller.h" + +#include "app/menus/menu_model.h" +#include "base/sys_string_conversions.h" +#include "chrome/app/chrome_dll_resource.h" +#import "chrome/browser/cocoa/toolbar_controller.h" +#include "chrome/browser/wrench_menu_model.h" + +@interface WrenchMenuController (Private) +- (WrenchMenuModel*)wrenchMenuModel; +- (void)adjustPositioning; +@end + +@implementation WrenchMenuController + +- (id)init { + self = [super init]; + return self; +} + +- (void)addItemToMenu:(NSMenu*)menu + atIndex:(NSInteger)index + fromModel:(menus::MenuModel*)model + modelIndex:(int)modelIndex { + // Non-button item types should be built as normal items. + menus::MenuModel::ItemType type = model->GetTypeAt(modelIndex); + if (type != menus::MenuModel::TYPE_BUTTON_ITEM) { + [super addItemToMenu:menu + atIndex:index + fromModel:model + modelIndex:modelIndex]; + return; + } + + // Handle the special-cased menu items. + int command_id = model->GetCommandIdAt(modelIndex); + scoped_nsobject<NSMenuItem> customItem( + [[NSMenuItem alloc] initWithTitle:@"" + action:nil + keyEquivalent:@""]); + switch (command_id) { + case IDC_EDIT_MENU: + DCHECK(editItem_); + [customItem setView:editItem_]; + break; + case IDC_ZOOM_MENU: + DCHECK(zoomItem_); + [customItem setView:zoomItem_]; + break; + default: + NOTREACHED(); + break; + } + [self adjustPositioning]; + [menu insertItem:customItem.get() atIndex:index]; +} + +- (NSMenu*)menu { + NSMenu* menu = [super menu]; + if (![menu delegate]) { + [menu setDelegate:self]; + } + return menu; +} + +- (void)menuWillOpen:(NSMenu*)menu { + NSString* title = base::SysUTF16ToNSString( + [self wrenchMenuModel]->GetLabelForCommandId(IDC_ZOOM_PERCENT_DISPLAY)); + [[zoomItem_ viewWithTag:IDC_ZOOM_PERCENT_DISPLAY] setTitle:title]; +} + +// Used to dispatch commands from the Wrench menu. The custom items within the +// menu cannot be hooked up directly to First Responder because the window in +// which the controls reside is not the BrowserWindowController, but a +// NSCarbonMenuWindow; this screws up the typical |-commandDispatch:| system. +- (IBAction)dispatchWrenchMenuCommand:(id)sender { + NSInteger tag = [sender tag]; + + // NSSegmentedControls (used for the Edit item) need a little help to get the + // command_id of the pressed item. + if ([sender isKindOfClass:[NSSegmentedControl class]]) + tag = [[sender cell] tagForSegment:[sender selectedSegment]]; + + // The custom views within the Wrench menu are abnormal and keep the menu open + // after a target-action. Close the menu manually. + // TODO(rsesek): It'd be great if the zoom buttons didn't have to close the + // menu. See http://crbug.com/48679 for more info. + [menu_ cancelTracking]; + [self wrenchMenuModel]->ExecuteCommand(tag); +} + +- (WrenchMenuModel*)wrenchMenuModel { + return static_cast<WrenchMenuModel*>(model_); +} + +// Fit the localized strings into the Cut/Copy/Paste control, then resize the +// whole menu item accordingly. +- (void)adjustPositioning { + NSRect itemFrame = [editItem_ frame]; + NSRect controlFrame = [editControl_ frame]; + + CGFloat originalControlWidth = NSWidth(controlFrame); + // Maintain the carefully pixel-pushed gap between the edge of the menu and + // the rightmost control. + CGFloat edge = NSWidth(itemFrame) - + (controlFrame.origin.x + originalControlWidth); + + // Resize the edit segmented control to fit the localized strings. + [editControl_ sizeToFit]; + controlFrame = [editControl_ frame]; + CGFloat resizeAmount = NSWidth(controlFrame) - originalControlWidth; + + // Adjust the size of the entire menu item to account for changes in the size + // of the segmented control. + itemFrame.size.width += resizeAmount; + [editItem_ setFrame:itemFrame]; + + // Keep the spacing between the right edges of the menu and the control. + controlFrame.origin.x = NSWidth(itemFrame) - edge - NSWidth(controlFrame); + [editControl_ setFrame:controlFrame]; +} + +@end // @implementation WrenchMenuController |