Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5771)

Unified Diff: chrome/browser/ui/cocoa/draggable_button_mixin.mm

Issue 7462018: [Mac] "Refactor" DraggableButton into a mixin and impl. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/cocoa/draggable_button_mixin.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/cocoa/draggable_button_mixin.mm
diff --git a/chrome/browser/ui/cocoa/draggable_button.mm b/chrome/browser/ui/cocoa/draggable_button_mixin.mm
similarity index 50%
copy from chrome/browser/ui/cocoa/draggable_button.mm
copy to chrome/browser/ui/cocoa/draggable_button_mixin.mm
index 4d03b2790ec78127546126e082bdf5dd4854b47c..a704498046064e48cb597e8f90ef40d896f2acc9 100644
--- a/chrome/browser/ui/cocoa/draggable_button.mm
+++ b/chrome/browser/ui/cocoa/draggable_button_mixin.mm
@@ -4,6 +4,8 @@
#import "chrome/browser/ui/cocoa/draggable_button.h"
+#include <cmath>
+
#include "base/logging.h"
#import "base/memory/scoped_nsobject.h"
@@ -17,7 +19,32 @@ const CGFloat kDragExpirationTimeout = 0.45;
}
-@implementation DraggableButton
+// Private /////////////////////////////////////////////////////////////////////
+
+@interface DraggableButtonImpl (Private)
+
+- (BOOL)deltaIndicatesDragStartWithXDelta:(float)xDelta
+ yDelta:(float)yDelta
+ xHysteresis:(float)xHysteresis
+ yHysteresis:(float)yHysteresis;
+- (BOOL)deltaIndicatesConclusionReachedWithXDelta:(float)xDelta
+ yDelta:(float)yDelta
+ xHysteresis:(float)xHysteresis
+ yHysteresis:(float)yHysteresis;
+- (void)performMouseDownAction:(NSEvent*)theEvent;
+- (void)endDrag;
+- (BOOL)dragShouldBeginFromMouseDown:(NSEvent*)mouseDownEvent
+ withExpiration:(NSDate*)expiration;
+- (BOOL)dragShouldBeginFromMouseDown:(NSEvent*)mouseDownEvent
+ withExpiration:(NSDate*)expiration
+ xHysteresis:(float)xHysteresis
+ yHysteresis:(float)yHysteresis;
+
+@end
+
+// Implementation //////////////////////////////////////////////////////////////
+
+@implementation DraggableButtonImpl
@synthesize draggable = draggable_;
@synthesize actsOnMouseDown = actsOnMouseDown_;
@@ -25,9 +52,9 @@ const CGFloat kDragExpirationTimeout = 0.45;
@synthesize actionHasFired = actionHasFired_;
@synthesize whenMouseDown = whenMouseDown_;
-
-- (id)initWithFrame:(NSRect)frame {
- if ((self = [super initWithFrame:frame])) {
+- (id)initWithButton:(NSButton<DraggableButtonMixin>*)button {
+ if ((self = [super init])) {
+ button_ = button;
draggable_ = YES;
actsOnMouseDown_ = NO;
actionHasFired_ = NO;
@@ -35,29 +62,117 @@ const CGFloat kDragExpirationTimeout = 0.45;
return self;
}
-- (id)initWithCoder:(NSCoder*)coder {
- if ((self = [super initWithCoder:coder])) {
- draggable_ = YES;
- actsOnMouseDown_ = NO;
- actionHasFired_ = NO;
+// NSButton/NSResponder Implementations ////////////////////////////////////////
+
+- (DraggableButtonResult)mouseUp:(NSEvent*)theEvent {
+ durationMouseWasDown_ = [theEvent timestamp] - whenMouseDown_;
+
+ if (actionHasFired_)
+ return kDraggableButtonImplDidWork;
+
+ if (!draggable_)
+ return kDraggableButtonMixinCallSuper;
+
+ // There are non-drag cases where a |-mouseUp:| may happen (e.g. mouse-down,
+ // cmd-tab to another application, move mouse, mouse-up), so check.
+ NSPoint viewLocal = [button_ convertPoint:[theEvent locationInWindow]
+ fromView:[[button_ window] contentView]];
+ if (NSPointInRect(viewLocal, [button_ bounds]))
+ [button_ performClick:self];
+
+ return kDraggableButtonImplDidWork;
+}
+
+// Mimic "begin a click" operation visually. Do NOT follow through with normal
+// button event handling.
+- (DraggableButtonResult)mouseDown:(NSEvent*)theEvent {
+ [[NSCursor arrowCursor] set];
+
+ whenMouseDown_ = [theEvent timestamp];
+ actionHasFired_ = NO;
+
+ if (draggable_) {
+ NSDate* date = [NSDate dateWithTimeIntervalSinceNow:kDragExpirationTimeout];
+ if ([self dragShouldBeginFromMouseDown:theEvent
+ withExpiration:date]) {
+ [button_ beginDrag:theEvent];
+ [self endDrag];
+ } else {
+ if (actsOnMouseDown_) {
+ [self performMouseDownAction:theEvent];
+ return kDraggableButtonImplDidWork;
+ } else {
+ return kDraggableButtonMixinCallSuper;
+ }
+ }
+ } else {
+ if (actsOnMouseDown_) {
+ [self performMouseDownAction:theEvent];
+ return kDraggableButtonImplDidWork;
+ } else {
+ return kDraggableButtonMixinCallSuper;
+ }
}
- return self;
+
+ return kDraggableButtonImplDidWork;
}
+// Idempotent Helpers //////////////////////////////////////////////////////////
+
- (BOOL)deltaIndicatesDragStartWithXDelta:(float)xDelta
yDelta:(float)yDelta
xHysteresis:(float)xHysteresis
yHysteresis:(float)yHysteresis {
- return (ABS(xDelta) >= xHysteresis) || (ABS(yDelta) >= yHysteresis);
+ if ([button_ respondsToSelector:@selector(deltaIndicatesDragStartWithXDelta:
+ yDelta:
+ xHysteresis:
+ yHysteresis:
+ indicates:)]) {
+ BOOL indicates = NO;
+ DraggableButtonResult result = [button_
+ deltaIndicatesDragStartWithXDelta:xDelta
+ yDelta:yDelta
+ xHysteresis:xHysteresis
+ yHysteresis:yHysteresis
+ indicates:&indicates];
+ if (result != kDraggableButtonImplUseBase)
+ return indicates;
+ }
+ return (std::abs(xDelta) >= xHysteresis) || (std::abs(yDelta) >= yHysteresis);
}
- (BOOL)deltaIndicatesConclusionReachedWithXDelta:(float)xDelta
yDelta:(float)yDelta
xHysteresis:(float)xHysteresis
yHysteresis:(float)yHysteresis {
- return (ABS(xDelta) >= xHysteresis) || (ABS(yDelta) >= yHysteresis);
+ if ([button_ respondsToSelector:
+ @selector(deltaIndicatesConclusionReachedWithXDelta:
+ yDelta:
+ xHysteresis:
+ yHysteresis:
+ indicates:)]) {
+ BOOL indicates = NO;
+ DraggableButtonResult result = [button_
+ deltaIndicatesConclusionReachedWithXDelta:xDelta
+ yDelta:yDelta
+ xHysteresis:xHysteresis
+ yHysteresis:yHysteresis
+ indicates:&indicates];
+ if (result != kDraggableButtonImplUseBase)
+ return indicates;
+ }
+ return (std::abs(xDelta) >= xHysteresis) || (std::abs(yDelta) >= yHysteresis);
+}
+
+- (BOOL)dragShouldBeginFromMouseDown:(NSEvent*)mouseDownEvent
+ withExpiration:(NSDate*)expiration {
+ return [self dragShouldBeginFromMouseDown:mouseDownEvent
+ withExpiration:expiration
+ xHysteresis:kWebDragStartHysteresisX
+ yHysteresis:kWebDragStartHysteresisY];
}
+// Implementation Details //////////////////////////////////////////////////////
// Determine whether a mouse down should turn into a drag; started as copy of
// NSTableView code.
@@ -75,8 +190,8 @@ const CGFloat kDragExpirationTimeout = 0.45;
NSEvent* mouseUp = nil;
BOOL dragIt = NO;
- while ((nextEvent = [[self window]
- nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask)
+ while ((nextEvent = [[button_ window]
+ nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask
untilDate:expiration
inMode:NSEventTrackingRunLoopMode
dequeue:YES]) != nil) {
@@ -122,107 +237,53 @@ const CGFloat kDragExpirationTimeout = 0.45;
return dragIt;
}
-- (BOOL)dragShouldBeginFromMouseDown:(NSEvent*)mouseDownEvent
- withExpiration:(NSDate*)expiration {
- return [self dragShouldBeginFromMouseDown:mouseDownEvent
- withExpiration:expiration
- xHysteresis:kWebDragStartHysteresisX
- yHysteresis:kWebDragStartHysteresisY];
-}
-
-- (void)mouseUp:(NSEvent*)theEvent {
- durationMouseWasDown_ = [theEvent timestamp] - whenMouseDown_;
-
- if (actionHasFired_)
- return;
-
- if (!draggable_) {
- [super mouseUp:theEvent];
- return;
- }
+- (void)secondaryMouseUpAction:(BOOL)wasInside {
+ if ([button_ respondsToSelector:_cmd])
+ [button_ secondaryMouseUpAction:wasInside];
- // 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];
- }
+ // No actual implementation yet.
}
-- (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*)event {
+ if ([button_ respondsToSelector:_cmd] &&
+ [button_ performMouseDownAction:event] != kDraggableButtonImplUseBase) {
+ return;
+ }
-- (void)performMouseDownAction:(NSEvent*)theEvent {
int eventMask = NSLeftMouseUpMask;
- [[self target] performSelector:[self action] withObject:self];
+ [[button_ target] performSelector:[button_ action] withObject:self];
actionHasFired_ = YES;
while (1) {
- theEvent = [[self window] nextEventMatchingMask:eventMask];
- if (!theEvent)
+ event = [[button_ window] nextEventMatchingMask:eventMask];
+ if (!event)
continue;
- NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow]
- fromView:nil];
- BOOL isInside = [self mouse:mouseLoc inRect:[self bounds]];
- [self highlight:isInside];
+ NSPoint mouseLoc = [button_ convertPoint:[event locationInWindow]
+ fromView:nil];
+ BOOL isInside = [button_ mouse:mouseLoc inRect:[button_ bounds]];
+ [button_ highlight:isInside];
- switch ([theEvent type]) {
+ switch ([event type]) {
case NSLeftMouseUp:
- durationMouseWasDown_ = [theEvent timestamp] - whenMouseDown_;
+ durationMouseWasDown_ = [event timestamp] - whenMouseDown_;
[self secondaryMouseUpAction:isInside];
break;
default:
- /* Ignore any other kind of event. */
+ // 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];
- }
- }
-}
-
-- (void)beginDrag:(NSEvent*)dragEvent {
- // Must be overridden by subclasses.
- NOTREACHED();
+ [button_ highlight:NO];
}
- (void)endDrag {
- [self highlight:NO];
+ if ([button_ respondsToSelector:_cmd] &&
+ [button_ endDrag] != kDraggableButtonImplUseBase) {
+ return;
+ }
+ [button_ highlight:NO];
}
-@end // @interface DraggableButton
+@end
« no previous file with comments | « chrome/browser/ui/cocoa/draggable_button_mixin.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698