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

Side by Side Diff: chrome/browser/ui/cocoa/draggable_button.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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/draggable_button.h" 5 #import "chrome/browser/ui/cocoa/draggable_button.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #import "base/memory/scoped_nsobject.h"
9
10 namespace {
11
12 // Code taken from <http://codereview.chromium.org/180036/diff/3001/3004>.
13 // TODO(viettrungluu): Do we want common, standard code for drag hysteresis?
14 const CGFloat kWebDragStartHysteresisX = 5.0;
15 const CGFloat kWebDragStartHysteresisY = 5.0;
16 const CGFloat kDragExpirationTimeout = 0.45;
17
18 }
19 8
20 @implementation DraggableButton 9 @implementation DraggableButton
21 10
22 @synthesize draggable = draggable_;
23 @synthesize actsOnMouseDown = actsOnMouseDown_;
24 @synthesize durationMouseWasDown = durationMouseWasDown_;
25 @synthesize actionHasFired = actionHasFired_;
26 @synthesize whenMouseDown = whenMouseDown_;
27
28
29 - (id)initWithFrame:(NSRect)frame { 11 - (id)initWithFrame:(NSRect)frame {
30 if ((self = [super initWithFrame:frame])) { 12 if ((self = [super initWithFrame:frame])) {
31 draggable_ = YES; 13 draggableButtonImpl_.reset(
32 actsOnMouseDown_ = NO; 14 [[DraggableButtonImpl alloc] initWithButton:self]);
33 actionHasFired_ = NO;
34 } 15 }
35 return self; 16 return self;
36 } 17 }
37 18
38 - (id)initWithCoder:(NSCoder*)coder { 19 - (id)initWithCoder:(NSCoder*)coder {
39 if ((self = [super initWithCoder:coder])) { 20 if ((self = [super initWithCoder:coder])) {
40 draggable_ = YES; 21 draggableButtonImpl_.reset(
41 actsOnMouseDown_ = NO; 22 [[DraggableButtonImpl alloc] initWithButton:self]);
42 actionHasFired_ = NO;
43 } 23 }
44 return self; 24 return self;
45 } 25 }
46 26
47 - (BOOL)deltaIndicatesDragStartWithXDelta:(float)xDelta 27 - (DraggableButtonImpl*)draggableButton {
48 yDelta:(float)yDelta 28 return draggableButtonImpl_.get();
49 xHysteresis:(float)xHysteresis
50 yHysteresis:(float)yHysteresis {
51 return (ABS(xDelta) >= xHysteresis) || (ABS(yDelta) >= yHysteresis);
52 }
53
54 - (BOOL)deltaIndicatesConclusionReachedWithXDelta:(float)xDelta
55 yDelta:(float)yDelta
56 xHysteresis:(float)xHysteresis
57 yHysteresis:(float)yHysteresis {
58 return (ABS(xDelta) >= xHysteresis) || (ABS(yDelta) >= yHysteresis);
59 }
60
61
62 // Determine whether a mouse down should turn into a drag; started as copy of
63 // NSTableView code.
64 - (BOOL)dragShouldBeginFromMouseDown:(NSEvent*)mouseDownEvent
65 withExpiration:(NSDate*)expiration
66 xHysteresis:(float)xHysteresis
67 yHysteresis:(float)yHysteresis {
68 if ([mouseDownEvent type] != NSLeftMouseDown) {
69 return NO;
70 }
71
72 NSEvent* nextEvent = nil;
73 NSEvent* firstEvent = nil;
74 NSEvent* dragEvent = nil;
75 NSEvent* mouseUp = nil;
76 BOOL dragIt = NO;
77
78 while ((nextEvent = [[self window]
79 nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask)
80 untilDate:expiration
81 inMode:NSEventTrackingRunLoopMode
82 dequeue:YES]) != nil) {
83 if (firstEvent == nil) {
84 firstEvent = nextEvent;
85 }
86 if ([nextEvent type] == NSLeftMouseDragged) {
87 float deltax = [nextEvent locationInWindow].x -
88 [mouseDownEvent locationInWindow].x;
89 float deltay = [nextEvent locationInWindow].y -
90 [mouseDownEvent locationInWindow].y;
91 dragEvent = nextEvent;
92 if ([self deltaIndicatesConclusionReachedWithXDelta:deltax
93 yDelta:deltay
94 xHysteresis:xHysteresis
95 yHysteresis:yHysteresis]) {
96 dragIt = [self deltaIndicatesDragStartWithXDelta:deltax
97 yDelta:deltay
98 xHysteresis:xHysteresis
99 yHysteresis:yHysteresis];
100 break;
101 }
102 } else if ([nextEvent type] == NSLeftMouseUp) {
103 mouseUp = nextEvent;
104 break;
105 }
106 }
107
108 // Since we've been dequeuing the events (If we don't, we'll never see
109 // the mouse up...), we need to push some of the events back on.
110 // It makes sense to put the first and last drag events and the mouse
111 // up if there was one.
112 if (mouseUp != nil) {
113 [NSApp postEvent:mouseUp atStart:YES];
114 }
115 if (dragEvent != nil) {
116 [NSApp postEvent:dragEvent atStart:YES];
117 }
118 if (firstEvent != mouseUp && firstEvent != dragEvent) {
119 [NSApp postEvent:firstEvent atStart:YES];
120 }
121
122 return dragIt;
123 }
124
125 - (BOOL)dragShouldBeginFromMouseDown:(NSEvent*)mouseDownEvent
126 withExpiration:(NSDate*)expiration {
127 return [self dragShouldBeginFromMouseDown:mouseDownEvent
128 withExpiration:expiration
129 xHysteresis:kWebDragStartHysteresisX
130 yHysteresis:kWebDragStartHysteresisY];
131 } 29 }
132 30
133 - (void)mouseUp:(NSEvent*)theEvent { 31 - (void)mouseUp:(NSEvent*)theEvent {
134 durationMouseWasDown_ = [theEvent timestamp] - whenMouseDown_; 32 if ([draggableButtonImpl_ mouseUp:theEvent] == kDraggableButtonMixinCallSuper)
33 [super mouseUp:theEvent];
34 }
135 35
136 if (actionHasFired_) 36 - (void)mouseDown:(NSEvent*)theEvent {
137 return; 37 if ([draggableButtonImpl_ mouseDown:theEvent] ==
138 38 kDraggableButtonMixinCallSuper) {
139 if (!draggable_) { 39 [super mouseDown:theEvent];
140 [super mouseUp:theEvent];
141 return;
142 }
143
144 // There are non-drag cases where a mouseUp: may happen
145 // (e.g. mouse-down, cmd-tab to another application, move mouse,
146 // mouse-up). So we check.
147 NSPoint viewLocal = [self convertPoint:[theEvent locationInWindow]
148 fromView:[[self window] contentView]];
149 if (NSPointInRect(viewLocal, [self bounds])) {
150 [self performClick:self];
151 } 40 }
152 } 41 }
153 42
154 - (void)secondaryMouseUpAction:(BOOL)wasInside {
155 // Override if you want to do any extra work on mouseUp, after a mouseDown
156 // action has already fired.
157 }
158
159 - (void)performMouseDownAction:(NSEvent*)theEvent {
160 int eventMask = NSLeftMouseUpMask;
161
162 [[self target] performSelector:[self action] withObject:self];
163 actionHasFired_ = YES;
164
165 while (1) {
166 theEvent = [[self window] nextEventMatchingMask:eventMask];
167 if (!theEvent)
168 continue;
169 NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow]
170 fromView:nil];
171 BOOL isInside = [self mouse:mouseLoc inRect:[self bounds]];
172 [self highlight:isInside];
173
174 switch ([theEvent type]) {
175 case NSLeftMouseUp:
176 durationMouseWasDown_ = [theEvent timestamp] - whenMouseDown_;
177 [self secondaryMouseUpAction:isInside];
178 break;
179 default:
180 /* Ignore any other kind of event. */
181 break;
182 }
183 }
184
185 [self highlight:NO];
186 }
187
188 // Mimic "begin a click" operation visually. Do NOT follow through
189 // with normal button event handling.
190 - (void)mouseDown:(NSEvent*)theEvent {
191 [[NSCursor arrowCursor] set];
192
193 whenMouseDown_ = [theEvent timestamp];
194 actionHasFired_ = NO;
195
196 if (draggable_) {
197 NSDate* date = [NSDate dateWithTimeIntervalSinceNow:kDragExpirationTimeout];
198 if ([self dragShouldBeginFromMouseDown:theEvent
199 withExpiration:date]) {
200 [self beginDrag:theEvent];
201 [self endDrag];
202 } else {
203 if (actsOnMouseDown_) {
204 [self performMouseDownAction:theEvent];
205 } else {
206 [super mouseDown:theEvent];
207 }
208
209 }
210 } else {
211 if (actsOnMouseDown_) {
212 [self performMouseDownAction:theEvent];
213 } else {
214 [super mouseDown:theEvent];
215 }
216 }
217 }
218
219 - (void)beginDrag:(NSEvent*)dragEvent { 43 - (void)beginDrag:(NSEvent*)dragEvent {
220 // Must be overridden by subclasses. 44 // Must be overridden by subclasses.
221 NOTREACHED(); 45 NOTREACHED();
222 } 46 }
223 47
224 - (void)endDrag {
225 [self highlight:NO];
226 }
227
228 @end // @interface DraggableButton 48 @end // @interface DraggableButton
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/draggable_button.h ('k') | chrome/browser/ui/cocoa/draggable_button_mixin.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698