summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/delayedmenu_button.mm
diff options
context:
space:
mode:
authoravi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-05 15:13:13 +0000
committeravi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-05 15:13:13 +0000
commit60114cc6a2ce3e8a5f910262aeac5d02dcdd5c30 (patch)
tree40fd04edbd5f8596bcc67b00faf6dddc295b6179 /chrome/browser/cocoa/delayedmenu_button.mm
parent32bd6419b3b6c6c11a3dbfb709f80772d954c752 (diff)
downloadchromium_src-60114cc6a2ce3e8a5f910262aeac5d02dcdd5c30.zip
chromium_src-60114cc6a2ce3e8a5f910262aeac5d02dcdd5c30.tar.gz
chromium_src-60114cc6a2ce3e8a5f910262aeac5d02dcdd5c30.tar.bz2
Implement back/forward toolbar menus on Mac (bug 13203).
Note: The drop-down menu is actually a drag-down (activating on click-hold or on drag), working much like Safari's (and other Apple apps, such as Dictionary). This can be changed to a pop-down if that's what's desired. [The previously included fix to bug 17990 has been split off to CL 159864.] TODO: Show keyboard shortcut for "Show Full History". Patch by viettrungluu. BUG=http://crbug.com/13203 TEST=Navigate around, check out and use the menus; do so in multiple tabs and windows. Review URL: http://codereview.chromium.org/160496 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22478 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cocoa/delayedmenu_button.mm')
-rw-r--r--chrome/browser/cocoa/delayedmenu_button.mm124
1 files changed, 124 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/delayedmenu_button.mm b/chrome/browser/cocoa/delayedmenu_button.mm
new file mode 100644
index 0000000..1470d1a
--- /dev/null
+++ b/chrome/browser/cocoa/delayedmenu_button.mm
@@ -0,0 +1,124 @@
+// 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/delayedmenu_button.h"
+
+#include "base/logging.h"
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/cocoa/clickhold_button_cell.h"
+
+@interface DelayedMenuButton (Private)
+
+- (void)resetToDefaults;
+- (void)menuAction:(id)sender;
+
+@end // @interface DelayedMenuButton (Private)
+
+@implementation DelayedMenuButton
+
+// 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;
+}
+
+- (void)awakeFromNib {
+ [self resetToDefaults];
+}
+
+// Accessors and mutators:
+
+@synthesize menu = menu_;
+
+// Don't synthesize for menuEnabled_; its mutator must do other things.
+- (void)setMenuEnabled:(BOOL)enabled {
+ menuEnabled_ = enabled;
+ [[self cell] setEnableClickHold:menuEnabled_];
+}
+
+- (BOOL)menuEnabled {
+ return menuEnabled_;
+}
+
+@end // @implementation DelayedMenuButton
+
+@implementation DelayedMenuButton (Private)
+
+- (void)resetToDefaults {
+ id cell = [self cell];
+ DCHECK([cell isKindOfClass:[ClickHoldButtonCell class]]);
+ [self setEnabled:NO]; // Make the controller put in a menu and
+ // enable it explicitly. This also takes
+ // care of |[cell setEnableClickHold:]|.
+ [cell setClickHoldTimeout:0.25]; // Random guess at Cocoa-ish value.
+ [cell setTrackOnlyInRect:NO];
+ [cell setActivateOnDrag:YES];
+ [cell setClickHoldAction:@selector(menuAction:)];
+ [cell setClickHoldTarget:self];
+}
+
+- (void)menuAction:(id)sender {
+ // We shouldn't get here unless the menu is enabled.
+ DCHECK(menuEnabled_);
+
+ // If we don't have a menu (in which case the person using this control is
+ // being bad), just wait for a mouse up.
+ if (!menu_) {
+ LOG(WARNING) << "No menu available.";
+ [NSApp nextEventMatchingMask:NSLeftMouseUpMask
+ untilDate:[NSDate distantFuture]
+ inMode:NSEventTrackingRunLoopMode
+ dequeue:YES];
+ return;
+ }
+
+ // FIXME(viettrungluu@gmail.com): Don't ask me. I don't know what's going on.
+ // But it yields unquestionably right results (even when the menu has to flip
+ // upwards because you've stupidly dragged the top of the window to the bottom
+ // of the screen) -- this demonstrates that the y-coordinate (in our
+ // superview's coordinates) is right. The x-coordinate (in our coordinates) is
+ // right since the menu appears horizontally in the right place (more or
+ // less). The |- 2.0| factor is an inexplicable fudge to make it approximately
+ // line up. If someone figures out what's going on, please fix this.
+ NSRect frame = [self frame];
+ frame.origin.x = [self convertPoint:frame.origin
+ fromView:[self superview]].x - 2.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<NSPopUpButtonCell> 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];
+}
+
+@end // @implementation DelayedMenuButton (Private)