From 1c977ab1081a4891419e40d6e4b1615c6e2583fb Mon Sep 17 00:00:00 2001 From: "viettrungluu@chromium.org" Date: Thu, 3 Sep 2009 20:42:24 +0000 Subject: (Mac) Make the Page/Wrench buttons place their menu in the right place. Also makes the buttons drag-able -- you can drag or click and wait to open their menu. Lucky for me, I wrote reusable code. To do (not now): The "off-the-end" button on the bookmark bar needs the same fix. Bug (not to be fixed now): The menu doesn't do the right thing when the window is moved off the left edge to the screen -- it doesn't open to the right in the correct fashion. Nor does it do the proper thing when you move the window off the bottom edge of the screen -- it doesn't open upwards entirely correctly. BUG=18572 TEST=Click on the Page and Wrench menu buttons and observe. Also test \ dragging to open. Review URL: http://codereview.chromium.org/174556 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25362 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/app/nibs/Toolbar.xib | 918 ++++++-------------------- chrome/browser/cocoa/clickhold_button_cell.h | 5 +- chrome/browser/cocoa/clickhold_button_cell.mm | 4 +- chrome/browser/cocoa/menu_button.h | 24 + chrome/browser/cocoa/menu_button.mm | 118 ++++ chrome/browser/cocoa/menu_button_unittest.mm | 64 ++ chrome/browser/cocoa/toolbar_controller.h | 15 +- chrome/browser/cocoa/toolbar_controller.mm | 13 +- chrome/chrome.gyp | 3 + 9 files changed, 403 insertions(+), 761 deletions(-) create mode 100644 chrome/browser/cocoa/menu_button.h create mode 100644 chrome/browser/cocoa/menu_button.mm create mode 100644 chrome/browser/cocoa/menu_button_unittest.mm (limited to 'chrome') diff --git a/chrome/app/nibs/Toolbar.xib b/chrome/app/nibs/Toolbar.xib index 2cab269..b35e64e 100644 --- a/chrome/app/nibs/Toolbar.xib +++ b/chrome/app/nibs/Toolbar.xib @@ -1,20 +1,16 @@ - + 1050 - 10A432 - 732 - 1038 - 437.00 - - com.apple.InterfaceBuilder.CocoaPlugin - 732 - + 9L31a + 677 + 949.54 + 353.00 YES - + YES @@ -22,7 +18,7 @@ YES - + YES @@ -58,7 +54,7 @@ chromium.org LucidaGrande - 13 + 1.300000e+01 16 @@ -96,7 +92,7 @@ LucidaGrande - 13 + 1.300000e+01 1044 @@ -124,8 +120,8 @@ 134250496 - -1 + -2030812929 6 @@ -179,8 +175,8 @@ 134250496 - 1 + -2031861505 6 @@ -205,8 +201,8 @@ 134250496 - -2 + -2030812929 6 @@ -231,8 +227,8 @@ 134250496 - 1 + -2031861505 6 @@ -258,8 +254,8 @@ - 140787967 - 6 + 141312255 + 134 NSImage menu_page_Template @@ -304,20 +300,28 @@ Page Menu YES - + - ^IDS_CREATE_SHORTCUTS + 2147483647 - + NSImage NSMenuCheckmark - + NSImage NSMenuMixedState + + + ^IDS_CREATE_SHORTCUTS + + 2147483647 + + + YES @@ -325,32 +329,32 @@ 2147483647 - - + + ^IDS_CUT 2147483647 - - + + ^IDS_COPY 2147483647 - - + + ^IDS_PASTE 2147483647 - - + + @@ -359,16 +363,16 @@ 2147483647 - - + + ^IDS_FIND 2147483647 - - + + 37000 @@ -376,8 +380,8 @@ ^IDS_SAVE_PAGE 2147483647 - - + + 35004 @@ -385,8 +389,8 @@ ^IDS_PRINT 2147483647 - - + + @@ -395,16 +399,16 @@ 2147483647 - - + + ^IDS_ZOOM_MENU 2147483647 - - + + submenuAction: ^IDS_ZOOM_MENU @@ -415,8 +419,8 @@ ^IDS_ZOOM_PLUS 2147483647 - - + + 38001 @@ -424,8 +428,8 @@ ^IDS_ZOOM_NORMAL 2147483647 - - + + 38002 @@ -433,8 +437,8 @@ ^IDS_ZOOM_MINUS 2147483647 - - + + 38003 @@ -445,8 +449,8 @@ ^IDS_ENCODING_MENU 2147483647 - - + + submenuAction: ^IDS_ENCODING_MENU @@ -457,8 +461,8 @@ Item 2147483647 - - + + @@ -470,16 +474,16 @@ 2147483647 - - + + ^IDS_DEVELOPER_MENU 2147483647 - - + + submenuAction: ^IDS_DEVELOPER_MENU @@ -490,8 +494,8 @@ ^IDS_VIEW_SOURCE 2147483647 - - + + 35001 @@ -499,16 +503,16 @@ ^IDS_DEV_TOOLS 2147483647 - - + + ^IDS_TASK_MANAGER 2147483647 - - + + @@ -520,16 +524,16 @@ 2147483647 - - + + ^IDS_REPORT_BUG 2147483647 - - + + 40008 @@ -538,13 +542,21 @@ Wrench Menu YES + + + + + 2147483647 + + + ^IDS_NEW_TAB 2147483647 - - + + 34014 @@ -552,8 +564,8 @@ ^IDS_NEW_WINDOW 2147483647 - - + + 34000 @@ -561,8 +573,8 @@ ^IDS_NEW_INCOGNITO_WINDOW 2147483647 - - + + 34001 @@ -572,16 +584,16 @@ 2147483647 - - + + ^IDS_BOOMARK_BAR_ALWAYS_SHOW 2147483647 - - + + 40009 @@ -589,8 +601,8 @@ ^IDS_FULLSCREEN 2147483647 - - + + 34030 @@ -600,16 +612,16 @@ 2147483647 - - + + ^IDS_SHOW_HISTORY 2147483647 - - + + 40010 @@ -617,16 +629,16 @@ ^IDS_BOOKMARK_MANAGER 2147483647 - - + + ^IDS_SHOW_DOWNLOADS 2147483647 - - + + 40012 @@ -636,16 +648,16 @@ 2147483647 - - + + ^IDS_PREFERENCES_MAC 2147483647 - - + + @@ -882,38 +894,6 @@ - showPageMenu: - - - - 89 - - - - showWrenchMenu: - - - - 90 - - - - pageMenu_ - - - - 91 - - - - wrenchMenu_ - - - - 92 - - - commandDispatch: @@ -1032,32 +1012,50 @@ 124 + + + menu_ + + + + 125 + + + + menu_ + + + + 126 + YES 0 - + + YES + -2 - - File's Owner + + RmlsZSdzIE93bmVyA -1 - + First Responder -3 - + Application @@ -1075,7 +1073,7 @@ - + 2 @@ -1224,8 +1222,9 @@ + - + 43 @@ -1259,8 +1258,9 @@ + - + 49 @@ -1468,13 +1468,23 @@ 122 - + + + + 127 + + + + + 129 + + YES - + YES -1.IBPluginDependency -2.IBPluginDependency @@ -1492,6 +1502,8 @@ 12.CustomClassName 12.IBPluginDependency 122.IBPluginDependency + 127.IBPluginDependency + 129.IBPluginDependency 13.CustomClassName 13.IBPluginDependency 14.CustomClassName @@ -1504,9 +1516,11 @@ 32.IBPluginDependency 33.CustomClassName 33.IBPluginDependency + 36.CustomClassName 36.IBPluginDependency 37.CustomClassName 37.IBPluginDependency + 38.CustomClassName 38.IBPluginDependency 39.CustomClassName 39.IBPluginDependency @@ -1577,6 +1591,8 @@ ToolbarButtonCell com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin AutocompleteTextFieldCell com.apple.InterfaceBuilder.CocoaPlugin ToolbarButtonCell @@ -1589,20 +1605,22 @@ com.apple.InterfaceBuilder.CocoaPlugin ToolbarButtonCell com.apple.InterfaceBuilder.CocoaPlugin + MenuButton com.apple.InterfaceBuilder.CocoaPlugin - GradientButtonCell + ClickHoldButtonCell com.apple.InterfaceBuilder.CocoaPlugin + MenuButton com.apple.InterfaceBuilder.CocoaPlugin - ToolbarButtonCell + ClickHoldButtonCell com.apple.InterfaceBuilder.CocoaPlugin AutocompleteTextField com.apple.InterfaceBuilder.CocoaPlugin - {{169, 524}, {232, 273}} + {{169, 463}, {235, 293}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{413, 588}, {303, 213}} + {{413, 523}, {306, 233}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -1647,7 +1665,9 @@ YES - + + YES + YES @@ -1655,13 +1675,15 @@ YES - + + YES + YES - 124 + 129 @@ -1671,7 +1693,7 @@ NSObject YES - + YES orderFrontStandardAboutPanel: quit: @@ -1686,7 +1708,7 @@ YES - + YES closeTabMenuItem_ closeWindowMenuItem_ @@ -1771,7 +1793,7 @@ NSObject YES - + YES otherObjectToLocalize_ owner_ @@ -1798,6 +1820,18 @@ + MenuButton + NSButton + + menu_ + NSMenu + + + IBProjectSource + browser/cocoa/menu_button.h + + + NSObject IBProjectSource @@ -1816,7 +1850,7 @@ NSWindowController YES - + YES addHomepage: clearData: @@ -1843,7 +1877,7 @@ YES - + YES advancedScroller_ advancedView_ @@ -1868,7 +1902,7 @@ NSViewController YES - + YES closeTab: commandDispatch: @@ -1881,9 +1915,8 @@ YES - + YES - backgroundButton_ closeButton_ contextMenu_ iconView_ @@ -1893,7 +1926,6 @@ YES NSButton - NSButton NSMenu NSView id @@ -1924,22 +1956,9 @@ ToolbarController NSViewController - - YES - - YES - showPageMenu: - showWrenchMenu: - - - YES - id - id - - YES - + YES backButton_ bookmarkBarDelegate_ @@ -1948,12 +1967,10 @@ homeButton_ locationBar_ pageButton_ - pageMenu_ reloadButton_ resizeDelegate_ starButton_ wrenchButton_ - wrenchMenu_ YES @@ -1963,13 +1980,11 @@ NSButton NSButton AutocompleteTextField - NSButton - NSMenu + MenuButton NSButton id NSButton - NSButton - NSMenu + MenuButton @@ -1994,573 +2009,8 @@ - - YES - - NSActionCell - NSCell - - IBFrameworkSource - AppKit.framework/Headers/NSActionCell.h - - - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSArrayController - NSObjectController - - IBFrameworkSource - AppKit.framework/Headers/NSArrayController.h - - - - NSButton - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSButton.h - - - - NSButtonCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSButtonCell.h - - - - NSCell - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSCell.h - - - - NSControl - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSController - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSController.h - - - - NSFormatter - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFormatter.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSMenuItem - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSMovieView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSMovieView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CIImageProvider.h - - - - NSObject - - IBFrameworkSource - SecurityInterface.framework/Headers/SFAuthorizationView.h - - - - NSObject - - IBFrameworkSource - SecurityInterface.framework/Headers/SFCertificatePanel.h - - - - NSObject - - IBFrameworkSource - SecurityInterface.framework/Headers/SFChooseIdentityPanel.h - - - - NSObjectController - NSController - - IBFrameworkSource - AppKit.framework/Headers/NSObjectController.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSScrollView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSScrollView.h - - - - NSTabView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSTabView.h - - - - NSText - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSText.h - - - - NSTextField - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSTextField.h - - - - NSTextFieldCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSTextFieldCell.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSViewController - NSResponder - - view - NSView - - - IBFrameworkSource - AppKit.framework/Headers/NSViewController.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h - - - - NSWindowController - NSResponder - - showWindow: - id - - - IBFrameworkSource - AppKit.framework/Headers/NSWindowController.h - - - 0 - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 - - - YES ../../chrome.xcodeproj 3 diff --git a/chrome/browser/cocoa/clickhold_button_cell.h b/chrome/browser/cocoa/clickhold_button_cell.h index 483336e..1982281 100644 --- a/chrome/browser/cocoa/clickhold_button_cell.h +++ b/chrome/browser/cocoa/clickhold_button_cell.h @@ -26,8 +26,9 @@ // Enable click-hold? Default: NO. @property(assign, nonatomic) BOOL enableClickHold; -// Timeout is in seconds (at least 0.01, at most 3600). Default: 0.25 (a guess -// at a Cocoa-ish value). +// Timeout is in seconds (at least 0.0, at most 5; 0.0 means that the button +// will always have its click-hold action activated immediately on press). +// Default: 0.25 (a guess at a Cocoa-ish value). @property(assign, nonatomic) NSTimeInterval clickHoldTimeout; // Track only in the frame rectangle? Default: NO. diff --git a/chrome/browser/cocoa/clickhold_button_cell.mm b/chrome/browser/cocoa/clickhold_button_cell.mm index 67b3df6..0dd5c3f 100644 --- a/chrome/browser/cocoa/clickhold_button_cell.mm +++ b/chrome/browser/cocoa/clickhold_button_cell.mm @@ -7,8 +7,8 @@ #include "base/logging.h" // Minimum and maximum click-hold timeout. -static const NSTimeInterval kMinTimeout = 0.01; -static const NSTimeInterval kMaxTimeout = 3600.0; +static const NSTimeInterval kMinTimeout = 0.0; +static const NSTimeInterval kMaxTimeout = 5.0; // Drag distance threshold to activate click-hold; should be >= 0. static const CGFloat kDragDistThreshold = 2.5; diff --git a/chrome/browser/cocoa/menu_button.h b/chrome/browser/cocoa/menu_button.h new file mode 100644 index 0000000..92b0569 --- /dev/null +++ b/chrome/browser/cocoa/menu_button.h @@ -0,0 +1,24 @@ +// 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. + +#ifndef CHROME_BROWSER_COCOA_MENU_BUTTON_H_ +#define CHROME_BROWSER_COCOA_MENU_BUTTON_H_ + +#import + +// This a button which displays a user-provided menu "attached" below it upon +// being clicked or dragged (or clicked and held). It expects a +// |ClickHoldButtonCell| as cell. +@interface MenuButton : NSButton { + @private + IBOutlet NSMenu* menu_; + BOOL openAtRight_; +} + +// The menu to display. +@property(assign, nonatomic) NSMenu* menu; + +@end // @interface MenuButton + +#endif // CHROME_BROWSER_COCOA_MENU_BUTTON_H_ diff --git a/chrome/browser/cocoa/menu_button.mm b/chrome/browser/cocoa/menu_button.mm new file mode 100644 index 0000000..aed8034 --- /dev/null +++ b/chrome/browser/cocoa/menu_button.mm @@ -0,0 +1,118 @@ +// 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_button.h" + +#include "base/logging.h" +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/clickhold_button_cell.h" + +@interface MenuButton (Private) + +- (void)resetToDefaults; +- (void)showMenu:(BOOL)isDragging; +- (void)clickShowMenu:(id)sender; +- (void)dragShowMenu:(id)sender; + +@end // @interface MenuButton (Private) + +@implementation MenuButton + +// Overrides: + ++ (Class)cellClass { + return [ClickHoldButtonCell class]; +} + +- (id)init { + if ((self = [super init])) + [self resetToDefaults]; + return self; +} + +- (id)initWithCoder:(NSCoder*)decoder { + if ((self = [super initWithCoder:decoder])) + [self resetToDefaults]; + return self; +} + +- (id)initWithFrame:(NSRect)frameRect { + if ((self = [super initWithFrame:frameRect])) + [self resetToDefaults]; + return self; +} + +// Accessors and mutators: + +@synthesize menu = menu_; + +@end // @implementation MenuButton + +@implementation MenuButton (Private) + +// Reset various settings of the button and its associated |ClickHoldButtonCell| +// to the standard state which provides reasonable defaults. +- (void)resetToDefaults { + id cell = [self cell]; + DCHECK([cell isKindOfClass:[ClickHoldButtonCell class]]); + [cell setEnableClickHold:YES]; + [cell setClickHoldTimeout:0.0]; // Make menu trigger immediately. + [cell setAction:@selector(clickShowMenu:)]; + [cell setTarget:self]; + [cell setClickHoldAction:@selector(dragShowMenu:)]; + [cell setClickHoldTarget:self]; +} + +// Actually show the menu (in the correct location). |isDragging| indicates +// whether the mouse button is still down or not. +- (void)showMenu:(BOOL)isDragging { + if (!menu_) { + LOG(WARNING) << "No menu available."; + if (isDragging) { + // If we're dragging, wait for mouse up. + [NSApp nextEventMatchingMask:NSLeftMouseUpMask + untilDate:[NSDate distantFuture] + inMode:NSEventTrackingRunLoopMode + dequeue:YES]; + } + return; + } + + // FIXME(viettrungluu): Silly fudge factors (same as in + // delayedmenu_button.mm). + NSRect frame = [self convertRect:[self frame] + fromView:[self superview]]; + frame.origin.x -= 2.0; + frame.size.height += 10.0; + + // Make our pop-up button cell and set things up. This is, as of 10.5, the + // official Apple-recommended hack. Later, perhaps |-[NSMenu + // popUpMenuPositioningItem:atLocation:inView:]| may be a better option. + // However, using a pulldown has the benefit that Cocoa automatically places + // the menu correctly even when we're at the edge of the screen (including + // "dragging upwards" when the button is close to the bottom of the screen). + scoped_nsobject popUpCell( + [[NSPopUpButtonCell alloc] initTextCell:@"" + pullsDown:YES]); + DCHECK(popUpCell.get()); + [popUpCell setMenu:menu_]; + [popUpCell selectItem:nil]; + [popUpCell attachPopUpWithFrame:frame + inView:self]; + [popUpCell performClickWithFrame:frame + inView:self]; +} + +// Called when the button is clicked and released. (Shouldn't happen with +// timeout of 0, though there may be some strange pointing devices out there.) +- (void)clickShowMenu:(id)sender { + [self showMenu:NO]; +} + +// Called when the button is clicked and dragged/held. +- (void)dragShowMenu:(id)sender { + [self showMenu:YES]; +} + +@end // @implementation MenuButton (Private) diff --git a/chrome/browser/cocoa/menu_button_unittest.mm b/chrome/browser/cocoa/menu_button_unittest.mm new file mode 100644 index 0000000..1861974 --- /dev/null +++ b/chrome/browser/cocoa/menu_button_unittest.mm @@ -0,0 +1,64 @@ +// 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 + +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/clickhold_button_cell.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#import "chrome/browser/cocoa/menu_button.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace { + +class MenuButtonTest : public PlatformTest { + public: + MenuButtonTest() { + NSRect frame = NSMakeRect(0, 0, 50, 30); + button_.reset([[MenuButton alloc] initWithFrame:frame]); + scoped_nsobject cell( + [[ClickHoldButtonCell alloc] initTextCell:@"Testing"]); + [button_ setCell:cell.get()]; + [cocoa_helper_.contentView() addSubview:button_.get()]; + } + + scoped_nsobject button_; + CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc. +}; + +// Test adding/removing from the view hierarchy, mostly to ensure nothing leaks +// or crashes. +TEST_F(MenuButtonTest, AddRemove) { + EXPECT_EQ(cocoa_helper_.contentView(), [button_ superview]); + [button_.get() removeFromSuperview]; + EXPECT_FALSE([button_ superview]); +} + +// Test drawing, mostly to ensure nothing leaks or crashes. +TEST_F(MenuButtonTest, Display) { + [button_ display]; +} + +// Test assigning a menu, again mostly to ensure nothing leaks or crashes. +TEST_F(MenuButtonTest, MenuAssign) { + scoped_nsobject menu([[NSMenu alloc] initWithTitle:@""]); + ASSERT_TRUE(menu.get()); + + [menu insertItemWithTitle:@"" action:nil keyEquivalent:@"" atIndex:0]; + [menu insertItemWithTitle:@"foo" action:nil keyEquivalent:@"" atIndex:1]; + [menu insertItemWithTitle:@"bar" action:nil keyEquivalent:@"" atIndex:2]; + [menu insertItemWithTitle:@"baz" action:nil keyEquivalent:@"" atIndex:3]; + + [button_ setMenu:menu]; + EXPECT_TRUE([button_ menu]); + + // TODO(viettrungluu): Display the menu. (The tough part is closing the menu, + // not opening it!) + + // Since |button_| doesn't retain menu, we should probably unset it here. + [button_ setMenu:nil]; +} + +} // namespace diff --git a/chrome/browser/cocoa/toolbar_controller.h b/chrome/browser/cocoa/toolbar_controller.h index f5819a5..a442d88 100644 --- a/chrome/browser/cocoa/toolbar_controller.h +++ b/chrome/browser/cocoa/toolbar_controller.h @@ -18,8 +18,9 @@ class AutocompletePopupPositioner; @class AutocompleteTextField; @class AutocompleteTextFieldEditor; -@class DelayedMenuButton; @class BackForwardMenuController; +@class DelayedMenuButton; +@class MenuButton; class Browser; class CommandUpdater; class LocationBar; @@ -69,9 +70,6 @@ class ToolbarView; scoped_nsobject trackingArea_; NSButton* hoveredButton_; // weak. Button under the mouse cursor. - IBOutlet NSMenu* pageMenu_; - IBOutlet NSMenu* wrenchMenu_; - // The ordering is important for unit tests. If new items are added or the // ordering is changed, make sure to update |-toolbarViews| and the // corresponding enum in the unit tests. @@ -81,8 +79,8 @@ class ToolbarView; IBOutlet NSButton* homeButton_; IBOutlet NSButton* starButton_; IBOutlet NSButton* goButton_; - IBOutlet NSButton* pageButton_; - IBOutlet NSButton* wrenchButton_; + IBOutlet MenuButton* pageButton_; + IBOutlet MenuButton* wrenchButton_; IBOutlet AutocompleteTextField* locationBar_; } @@ -130,11 +128,6 @@ class ToolbarView; // Return the bookmark bar controller. - (BookmarkBarController*)bookmarkBarController; -// Actions for the optional menu buttons for the page and wrench menus. These -// will show a menu while the mouse is down. -- (IBAction)showPageMenu:(id)sender; -- (IBAction)showWrenchMenu:(id)sender; - // The bookmark bubble (when you click the star) needs to know where to go. // Somewhere near the star button seems like a good start. - (NSRect)starButtonInWindowCoordinates; diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm index 5db38fb..4127615 100644 --- a/chrome/browser/cocoa/toolbar_controller.mm +++ b/chrome/browser/cocoa/toolbar_controller.mm @@ -14,6 +14,7 @@ #import "chrome/browser/cocoa/back_forward_menu_controller.h" #import "chrome/browser/cocoa/gradient_button_cell.h" #import "chrome/browser/cocoa/location_bar_view_mac.h" +#import "chrome/browser/cocoa/menu_button.h" #include "chrome/browser/cocoa/nsimage_cache.h" #include "chrome/browser/profile.h" #include "chrome/browser/toolbar_model.h" @@ -425,18 +426,6 @@ class PrefObserverBridge : public NotificationObserver { } } -- (IBAction)showPageMenu:(id)sender { - [NSMenu popUpContextMenu:pageMenu_ - withEvent:[NSApp currentEvent] - forView:pageButton_]; -} - -- (IBAction)showWrenchMenu:(id)sender { - [NSMenu popUpContextMenu:wrenchMenu_ - withEvent:[NSApp currentEvent] - forView:wrenchButton_]; -} - - (NSRect)starButtonInWindowCoordinates { return [[[starButton_ window] contentView] convertRect:[starButton_ bounds] fromView:starButton_]; diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 807cc50..c7e50f3 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -949,6 +949,8 @@ 'browser/cocoa/infobar_text_field.mm', 'browser/cocoa/location_bar_view_mac.h', 'browser/cocoa/location_bar_view_mac.mm', + 'browser/cocoa/menu_button.h', + 'browser/cocoa/menu_button.mm', 'browser/cocoa/nsimage_cache.h', 'browser/cocoa/nsimage_cache.mm', 'browser/cocoa/page_info_window_controller.h', @@ -3996,6 +3998,7 @@ 'browser/cocoa/gradient_button_cell_unittest.mm', 'browser/cocoa/history_menu_bridge_unittest.mm', 'browser/cocoa/history_menu_cocoa_controller_unittest.mm', + 'browser/cocoa/menu_button_unittest.mm', 'browser/cocoa/nsimage_cache_unittest.mm', 'browser/cocoa/page_info_window_controller_unittest.mm', 'browser/cocoa/preferences_window_controller_unittest.mm', -- cgit v1.1