| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #import "chrome/browser/cocoa/delayedmenu_button.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/scoped_nsobject.h" |
| 9 #import "chrome/browser/cocoa/clickhold_button_cell.h" |
| 10 |
| 11 @interface DelayedMenuButton (Private) |
| 12 |
| 13 - (void)resetToDefaults; |
| 14 - (void)menuAction:(id)sender; |
| 15 |
| 16 @end // @interface DelayedMenuButton (Private) |
| 17 |
| 18 @implementation DelayedMenuButton |
| 19 |
| 20 // Overrides: |
| 21 |
| 22 + (Class)cellClass { |
| 23 return [ClickHoldButtonCell class]; |
| 24 } |
| 25 |
| 26 - (id)init { |
| 27 if ((self = [super init])) |
| 28 [self resetToDefaults]; |
| 29 return self; |
| 30 } |
| 31 |
| 32 - (id)initWithCoder:(NSCoder*)decoder { |
| 33 if ((self = [super initWithCoder:decoder])) |
| 34 [self resetToDefaults]; |
| 35 return self; |
| 36 } |
| 37 |
| 38 - (id)initWithFrame:(NSRect)frameRect { |
| 39 if ((self = [super initWithFrame:frameRect])) |
| 40 [self resetToDefaults]; |
| 41 return self; |
| 42 } |
| 43 |
| 44 - (void)dealloc { |
| 45 [menu_ release]; |
| 46 [super dealloc]; |
| 47 } |
| 48 |
| 49 - (void)awakeFromNib { |
| 50 [self resetToDefaults]; |
| 51 } |
| 52 |
| 53 // Accessors and mutators: |
| 54 |
| 55 @synthesize menu = menu_; |
| 56 |
| 57 // Don't synthesize for menuEnabled_; its mutator must do other things. |
| 58 - (void)setMenuEnabled:(BOOL)enabled { |
| 59 menuEnabled_ = enabled; |
| 60 [[self cell] setEnableClickHold:menuEnabled_]; |
| 61 } |
| 62 |
| 63 - (BOOL)menuEnabled { |
| 64 return menuEnabled_; |
| 65 } |
| 66 |
| 67 @end // @implementation DelayedMenuButton |
| 68 |
| 69 @implementation DelayedMenuButton (Private) |
| 70 |
| 71 - (void)resetToDefaults { |
| 72 id cell = [self cell]; |
| 73 DCHECK([cell isKindOfClass:[ClickHoldButtonCell class]]); |
| 74 [self setEnabled:NO]; // Make the controller put in a menu and |
| 75 // enable it explicitly. This also takes |
| 76 // care of |[cell setEnableClickHold:]|. |
| 77 [cell setClickHoldTimeout:0.25]; // Random guess at Cocoa-ish value. |
| 78 [cell setTrackOnlyInRect:NO]; |
| 79 [cell setActivateOnDrag:YES]; |
| 80 [cell setClickHoldAction:@selector(menuAction:)]; |
| 81 [cell setClickHoldTarget:self]; |
| 82 } |
| 83 |
| 84 - (void)menuAction:(id)sender { |
| 85 // We shouldn't get here unless the menu is enabled. |
| 86 DCHECK(menuEnabled_); |
| 87 |
| 88 // If we don't have a menu (in which case the person using this control is |
| 89 // being bad), just wait for a mouse up. |
| 90 if (!menu_) { |
| 91 LOG(WARNING) << "No menu available."; |
| 92 [NSApp nextEventMatchingMask:NSLeftMouseUpMask |
| 93 untilDate:[NSDate distantFuture] |
| 94 inMode:NSEventTrackingRunLoopMode |
| 95 dequeue:YES]; |
| 96 return; |
| 97 } |
| 98 |
| 99 // FIXME(viettrungluu@gmail.com): Don't ask me. I don't know what's going on. |
| 100 // But it yields unquestionably right results (even when the menu has to flip |
| 101 // upwards because you've stupidly dragged the top of the window to the bottom |
| 102 // of the screen) -- this demonstrates that the y-coordinate (in our |
| 103 // superview's coordinates) is right. The x-coordinate (in our coordinates) is |
| 104 // right since the menu appears horizontally in the right place (more or |
| 105 // less). The |- 2.0| factor is an inexplicable fudge to make it approximately |
| 106 // line up. If someone figures out what's going on, please fix this. |
| 107 NSRect frame = [self frame]; |
| 108 frame.origin.x = [self convertPoint:frame.origin |
| 109 fromView:[self superview]].x - 2.0; |
| 110 |
| 111 // Make our pop-up button cell and set things up. This is, as of 10.5, the |
| 112 // official Apple-recommended hack. Later, perhaps |-[NSMenu |
| 113 // popUpMenuPositioningItem:atLocation:inView:]| may be a better option. |
| 114 // However, using a pulldown has the benefit that Cocoa automatically places |
| 115 // the menu correctly even when we're at the edge of the screen (including |
| 116 // "dragging upwards" when the button is close to the bottom of the screen). |
| 117 scoped_nsobject<NSPopUpButtonCell> popUpCell( |
| 118 [[NSPopUpButtonCell alloc] initTextCell:@"" |
| 119 pullsDown:YES]); |
| 120 DCHECK(popUpCell.get()); |
| 121 [popUpCell setMenu:menu_]; |
| 122 [popUpCell selectItem:nil]; |
| 123 [popUpCell attachPopUpWithFrame:frame |
| 124 inView:self]; |
| 125 [popUpCell performClickWithFrame:frame |
| 126 inView:self]; |
| 127 } |
| 128 |
| 129 @end // @implementation DelayedMenuButton (Private) |
| OLD | NEW |