| Index: chrome/browser/ui/cocoa/draggable_button.mm
|
| diff --git a/chrome/browser/ui/cocoa/draggable_button.mm b/chrome/browser/ui/cocoa/draggable_button.mm
|
| index 4d03b2790ec78127546126e082bdf5dd4854b47c..5654d58a04b8c79d821b251a3c955fd2a6b7cd21 100644
|
| --- a/chrome/browser/ui/cocoa/draggable_button.mm
|
| +++ b/chrome/browser/ui/cocoa/draggable_button.mm
|
| @@ -5,214 +5,38 @@
|
| #import "chrome/browser/ui/cocoa/draggable_button.h"
|
|
|
| #include "base/logging.h"
|
| -#import "base/memory/scoped_nsobject.h"
|
| -
|
| -namespace {
|
| -
|
| -// Code taken from <http://codereview.chromium.org/180036/diff/3001/3004>.
|
| -// TODO(viettrungluu): Do we want common, standard code for drag hysteresis?
|
| -const CGFloat kWebDragStartHysteresisX = 5.0;
|
| -const CGFloat kWebDragStartHysteresisY = 5.0;
|
| -const CGFloat kDragExpirationTimeout = 0.45;
|
| -
|
| -}
|
|
|
| @implementation DraggableButton
|
|
|
| -@synthesize draggable = draggable_;
|
| -@synthesize actsOnMouseDown = actsOnMouseDown_;
|
| -@synthesize durationMouseWasDown = durationMouseWasDown_;
|
| -@synthesize actionHasFired = actionHasFired_;
|
| -@synthesize whenMouseDown = whenMouseDown_;
|
| -
|
| -
|
| - (id)initWithFrame:(NSRect)frame {
|
| if ((self = [super initWithFrame:frame])) {
|
| - draggable_ = YES;
|
| - actsOnMouseDown_ = NO;
|
| - actionHasFired_ = NO;
|
| + draggableButtonImpl_.reset(
|
| + [[DraggableButtonImpl alloc] initWithButton:self]);
|
| }
|
| return self;
|
| }
|
|
|
| - (id)initWithCoder:(NSCoder*)coder {
|
| if ((self = [super initWithCoder:coder])) {
|
| - draggable_ = YES;
|
| - actsOnMouseDown_ = NO;
|
| - actionHasFired_ = NO;
|
| + draggableButtonImpl_.reset(
|
| + [[DraggableButtonImpl alloc] initWithButton:self]);
|
| }
|
| return self;
|
| }
|
|
|
| -- (BOOL)deltaIndicatesDragStartWithXDelta:(float)xDelta
|
| - yDelta:(float)yDelta
|
| - xHysteresis:(float)xHysteresis
|
| - yHysteresis:(float)yHysteresis {
|
| - return (ABS(xDelta) >= xHysteresis) || (ABS(yDelta) >= yHysteresis);
|
| -}
|
| -
|
| -- (BOOL)deltaIndicatesConclusionReachedWithXDelta:(float)xDelta
|
| - yDelta:(float)yDelta
|
| - xHysteresis:(float)xHysteresis
|
| - yHysteresis:(float)yHysteresis {
|
| - return (ABS(xDelta) >= xHysteresis) || (ABS(yDelta) >= yHysteresis);
|
| -}
|
| -
|
| -
|
| -// Determine whether a mouse down should turn into a drag; started as copy of
|
| -// NSTableView code.
|
| -- (BOOL)dragShouldBeginFromMouseDown:(NSEvent*)mouseDownEvent
|
| - withExpiration:(NSDate*)expiration
|
| - xHysteresis:(float)xHysteresis
|
| - yHysteresis:(float)yHysteresis {
|
| - if ([mouseDownEvent type] != NSLeftMouseDown) {
|
| - return NO;
|
| - }
|
| -
|
| - NSEvent* nextEvent = nil;
|
| - NSEvent* firstEvent = nil;
|
| - NSEvent* dragEvent = nil;
|
| - NSEvent* mouseUp = nil;
|
| - BOOL dragIt = NO;
|
| -
|
| - while ((nextEvent = [[self window]
|
| - nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask)
|
| - untilDate:expiration
|
| - inMode:NSEventTrackingRunLoopMode
|
| - dequeue:YES]) != nil) {
|
| - if (firstEvent == nil) {
|
| - firstEvent = nextEvent;
|
| - }
|
| - if ([nextEvent type] == NSLeftMouseDragged) {
|
| - float deltax = [nextEvent locationInWindow].x -
|
| - [mouseDownEvent locationInWindow].x;
|
| - float deltay = [nextEvent locationInWindow].y -
|
| - [mouseDownEvent locationInWindow].y;
|
| - dragEvent = nextEvent;
|
| - if ([self deltaIndicatesConclusionReachedWithXDelta:deltax
|
| - yDelta:deltay
|
| - xHysteresis:xHysteresis
|
| - yHysteresis:yHysteresis]) {
|
| - dragIt = [self deltaIndicatesDragStartWithXDelta:deltax
|
| - yDelta:deltay
|
| - xHysteresis:xHysteresis
|
| - yHysteresis:yHysteresis];
|
| - break;
|
| - }
|
| - } else if ([nextEvent type] == NSLeftMouseUp) {
|
| - mouseUp = nextEvent;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - // Since we've been dequeuing the events (If we don't, we'll never see
|
| - // the mouse up...), we need to push some of the events back on.
|
| - // It makes sense to put the first and last drag events and the mouse
|
| - // up if there was one.
|
| - if (mouseUp != nil) {
|
| - [NSApp postEvent:mouseUp atStart:YES];
|
| - }
|
| - if (dragEvent != nil) {
|
| - [NSApp postEvent:dragEvent atStart:YES];
|
| - }
|
| - if (firstEvent != mouseUp && firstEvent != dragEvent) {
|
| - [NSApp postEvent:firstEvent atStart:YES];
|
| - }
|
| -
|
| - return dragIt;
|
| -}
|
| -
|
| -- (BOOL)dragShouldBeginFromMouseDown:(NSEvent*)mouseDownEvent
|
| - withExpiration:(NSDate*)expiration {
|
| - return [self dragShouldBeginFromMouseDown:mouseDownEvent
|
| - withExpiration:expiration
|
| - xHysteresis:kWebDragStartHysteresisX
|
| - yHysteresis:kWebDragStartHysteresisY];
|
| +- (DraggableButtonImpl*)draggableButton {
|
| + return draggableButtonImpl_.get();
|
| }
|
|
|
| - (void)mouseUp:(NSEvent*)theEvent {
|
| - durationMouseWasDown_ = [theEvent timestamp] - whenMouseDown_;
|
| -
|
| - if (actionHasFired_)
|
| - return;
|
| -
|
| - if (!draggable_) {
|
| + if ([draggableButtonImpl_ mouseUp:theEvent] == kDraggableButtonMixinCallSuper)
|
| [super mouseUp:theEvent];
|
| - return;
|
| - }
|
| -
|
| - // There are non-drag cases where a mouseUp: may happen
|
| - // (e.g. mouse-down, cmd-tab to another application, move mouse,
|
| - // mouse-up). So we check.
|
| - NSPoint viewLocal = [self convertPoint:[theEvent locationInWindow]
|
| - fromView:[[self window] contentView]];
|
| - if (NSPointInRect(viewLocal, [self bounds])) {
|
| - [self performClick:self];
|
| - }
|
| -}
|
| -
|
| -- (void)secondaryMouseUpAction:(BOOL)wasInside {
|
| - // Override if you want to do any extra work on mouseUp, after a mouseDown
|
| - // action has already fired.
|
| -}
|
| -
|
| -- (void)performMouseDownAction:(NSEvent*)theEvent {
|
| - int eventMask = NSLeftMouseUpMask;
|
| -
|
| - [[self target] performSelector:[self action] withObject:self];
|
| - actionHasFired_ = YES;
|
| -
|
| - while (1) {
|
| - theEvent = [[self window] nextEventMatchingMask:eventMask];
|
| - if (!theEvent)
|
| - continue;
|
| - NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow]
|
| - fromView:nil];
|
| - BOOL isInside = [self mouse:mouseLoc inRect:[self bounds]];
|
| - [self highlight:isInside];
|
| -
|
| - switch ([theEvent type]) {
|
| - case NSLeftMouseUp:
|
| - durationMouseWasDown_ = [theEvent timestamp] - whenMouseDown_;
|
| - [self secondaryMouseUpAction:isInside];
|
| - break;
|
| - default:
|
| - /* Ignore any other kind of event. */
|
| - break;
|
| - }
|
| - }
|
| -
|
| - [self highlight:NO];
|
| }
|
|
|
| -// Mimic "begin a click" operation visually. Do NOT follow through
|
| -// with normal button event handling.
|
| - (void)mouseDown:(NSEvent*)theEvent {
|
| - [[NSCursor arrowCursor] set];
|
| -
|
| - whenMouseDown_ = [theEvent timestamp];
|
| - actionHasFired_ = NO;
|
| -
|
| - if (draggable_) {
|
| - NSDate* date = [NSDate dateWithTimeIntervalSinceNow:kDragExpirationTimeout];
|
| - if ([self dragShouldBeginFromMouseDown:theEvent
|
| - withExpiration:date]) {
|
| - [self beginDrag:theEvent];
|
| - [self endDrag];
|
| - } else {
|
| - if (actsOnMouseDown_) {
|
| - [self performMouseDownAction:theEvent];
|
| - } else {
|
| - [super mouseDown:theEvent];
|
| - }
|
| -
|
| - }
|
| - } else {
|
| - if (actsOnMouseDown_) {
|
| - [self performMouseDownAction:theEvent];
|
| - } else {
|
| - [super mouseDown:theEvent];
|
| - }
|
| + if ([draggableButtonImpl_ mouseDown:theEvent] ==
|
| + kDraggableButtonMixinCallSuper) {
|
| + [super mouseDown:theEvent];
|
| }
|
| }
|
|
|
| @@ -221,8 +45,4 @@ const CGFloat kDragExpirationTimeout = 0.45;
|
| NOTREACHED();
|
| }
|
|
|
| -- (void)endDrag {
|
| - [self highlight:NO];
|
| -}
|
| -
|
| @end // @interface DraggableButton
|
|
|