summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/cocoa/draggable_button.mm
diff options
context:
space:
mode:
authorrsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-11 19:17:41 +0000
committerrsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-11 19:17:41 +0000
commit4f61f537c43fcc72052f5263c1c26f48ee97eb96 (patch)
treef1671cc15574c1af9e1c533c2f85fabe72eb90ed /chrome/browser/ui/cocoa/draggable_button.mm
parenta195ec3629bca0b7f77130a8345e991b9fa28d7b (diff)
downloadchromium_src-4f61f537c43fcc72052f5263c1c26f48ee97eb96.zip
chromium_src-4f61f537c43fcc72052f5263c1c26f48ee97eb96.tar.gz
chromium_src-4f61f537c43fcc72052f5263c1c26f48ee97eb96.tar.bz2
[Mac] "Refactor" DraggableButton into a mixin and impl.
This is because DraggableButton inherits from NSButton when a future class will need it to inherit from NSPopupButton. Because ObjC lacks multiple inheritance, and we want to avoid runtime trickery, this is the result. BUG=none TEST=Dragging download shelf and bookmark bar items works as before. Partially covered by unit tests. Review URL: http://codereview.chromium.org/7462018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96433 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui/cocoa/draggable_button.mm')
-rw-r--r--chrome/browser/ui/cocoa/draggable_button.mm200
1 files changed, 10 insertions, 190 deletions
diff --git a/chrome/browser/ui/cocoa/draggable_button.mm b/chrome/browser/ui/cocoa/draggable_button.mm
index 4d03b27..5654d58 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