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 |