| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #include "base/logging.h" | 5 #include "base/logging.h" |
| 6 #import "base/scoped_nsobject.h" | 6 #import "base/scoped_nsobject.h" |
| 7 #import "chrome/browser/cocoa/bookmark_button.h" | 7 #import "chrome/browser/cocoa/bookmark_button.h" |
| 8 #import "chrome/browser/cocoa/bookmark_button_cell.h" | 8 #import "chrome/browser/cocoa/bookmark_button_cell.h" |
| 9 #import "third_party/GTM/AppKit/GTMTheme.h" | |
| 10 | |
| 11 namespace { | |
| 12 | |
| 13 // Code taken from <http://codereview.chromium.org/180036/diff/3001/3004>. | |
| 14 // TODO(viettrungluu): Do we want common, standard code for drag hysteresis? | |
| 15 const CGFloat kWebDragStartHysteresisX = 5.0; | |
| 16 const CGFloat kWebDragStartHysteresisY = 5.0; | |
| 17 | 9 |
| 18 // The opacity of the bookmark button drag image. | 10 // The opacity of the bookmark button drag image. |
| 19 const CGFloat kDragImageOpacity = 0.7; | 11 static const CGFloat kDragImageOpacity = 0.7; |
| 20 | |
| 21 } | |
| 22 | 12 |
| 23 @interface BookmarkButton(Private) | 13 @interface BookmarkButton(Private) |
| 24 | 14 |
| 25 // Make a drag image for the button. | 15 // Make a drag image for the button. |
| 26 - (NSImage*)dragImage; | 16 - (NSImage*)dragImage; |
| 27 | 17 |
| 28 @end // @interface BookmarkButton(Private) | 18 @end // @interface BookmarkButton(Private) |
| 29 | 19 |
| 30 @implementation BookmarkButton | 20 @implementation BookmarkButton |
| 31 | 21 |
| 32 @synthesize draggable = draggable_; | |
| 33 @synthesize delegate = delegate_; | 22 @synthesize delegate = delegate_; |
| 34 | 23 |
| 35 - (id)initWithFrame:(NSRect)frame { | |
| 36 if ((self = [super initWithFrame:frame])) { | |
| 37 draggable_ = YES; | |
| 38 } | |
| 39 return self; | |
| 40 } | |
| 41 | |
| 42 // By default, NSButton ignores middle-clicks. | 24 // By default, NSButton ignores middle-clicks. |
| 43 - (void)otherMouseUp:(NSEvent*)event { | 25 - (void)otherMouseUp:(NSEvent*)event { |
| 44 [self performClick:self]; | 26 [self performClick:self]; |
| 45 } | 27 } |
| 46 | 28 |
| 29 // Overridden from DraggableButton. |
| 47 - (void)beginDrag:(NSEvent*)event { | 30 - (void)beginDrag:(NSEvent*)event { |
| 48 // Starting drag. Never start another drag until another mouse down. | |
| 49 mayDragStart_ = NO; | |
| 50 | |
| 51 if (delegate_) { | 31 if (delegate_) { |
| 52 // Ask our delegate to fill the pasteboard for us. | 32 // Ask our delegate to fill the pasteboard for us. |
| 53 NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; | 33 NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; |
| 54 | 34 |
| 55 [delegate_ fillPasteboard:pboard forDragOfButton:self]; | 35 [delegate_ fillPasteboard:pboard forDragOfButton:self]; |
| 56 | 36 |
| 57 // At the moment, moving bookmarks causes their buttons (like me!) | 37 // At the moment, moving bookmarks causes their buttons (like me!) |
| 58 // to be destroyed and rebuilt. Make sure we don't go away while on | 38 // to be destroyed and rebuilt. Make sure we don't go away while on |
| 59 // the stack. | 39 // the stack. |
| 60 [self retain]; | 40 [self retain]; |
| 61 | 41 |
| 62 CGFloat yAt = [self bounds].size.height; | 42 CGFloat yAt = [self bounds].size.height; |
| 63 NSSize dragOffset = NSMakeSize(0.0, 0.0); | 43 NSSize dragOffset = NSMakeSize(0.0, 0.0); |
| 64 [self dragImage:[self dragImage] at:NSMakePoint(0, yAt) offset:dragOffset | 44 [self dragImage:[self dragImage] at:NSMakePoint(0, yAt) offset:dragOffset |
| 65 event:event pasteboard:pboard source:self slideBack:YES]; | 45 event:event pasteboard:pboard source:self slideBack:YES]; |
| 66 | 46 |
| 67 // And we're done. | 47 // And we're done.» |
| 68 [self autorelease]; | 48 [self autorelease]; |
| 69 } else { | 49 } else { |
| 70 // Avoid blowing up, but we really shouldn't get here. | 50 // Avoid blowing up, but we really shouldn't get here. |
| 71 NOTREACHED(); | 51 NOTREACHED(); |
| 72 } | 52 } |
| 73 } | 53 } |
| 74 | 54 |
| 75 - (void)draggedImage:(NSImage*)anImage | 55 - (void)draggedImage:(NSImage*)anImage |
| 76 endedAt:(NSPoint)aPoint | 56 endedAt:(NSPoint)aPoint |
| 77 operation:(NSDragOperation)operation { | 57 operation:(NSDragOperation)operation { |
| 78 beingDragged_ = NO; | 58 [super endDrag]; |
| 79 [[self cell] setHighlighted:NO]; | |
| 80 } | 59 } |
| 81 | 60 |
| 82 - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { | 61 - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { |
| 83 return isLocal ? NSDragOperationCopy | NSDragOperationMove | 62 return isLocal ? NSDragOperationCopy | NSDragOperationMove |
| 84 : NSDragOperationCopy; | 63 : NSDragOperationCopy; |
| 85 } | 64 } |
| 86 | 65 |
| 87 - (void)mouseUp:(NSEvent*)theEvent { | |
| 88 // Make sure that we can't start a drag until we see a mouse down again. | |
| 89 mayDragStart_ = NO; | |
| 90 | |
| 91 // This conditional is never true (DnD loops in Cocoa eat the mouse | |
| 92 // up) but I added it in case future versions of Cocoa do unexpected | |
| 93 // things. | |
| 94 if (beingDragged_) { | |
| 95 NOTREACHED(); | |
| 96 return [super mouseUp:theEvent]; | |
| 97 } | |
| 98 | |
| 99 // There are non-drag cases where a mouseUp: may happen | |
| 100 // (e.g. mouse-down, cmd-tab to another application, move mouse, | |
| 101 // mouse-up). So we check. | |
| 102 NSPoint viewLocal = [self convertPoint:[theEvent locationInWindow] | |
| 103 fromView:[[self window] contentView]]; | |
| 104 if (NSPointInRect(viewLocal, [self bounds])) { | |
| 105 [self performClick:self]; | |
| 106 } else { | |
| 107 [[self cell] setHighlighted:NO]; | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 // Mimic "begin a click" operation visually. Do NOT follow through | |
| 112 // with normal button event handling. | |
| 113 - (void)mouseDown:(NSEvent*)theEvent { | |
| 114 mayDragStart_ = YES; | |
| 115 [[self cell] setHighlighted:YES]; | |
| 116 initialMouseDownLocation_ = [theEvent locationInWindow]; | |
| 117 } | |
| 118 | |
| 119 // Return YES if we have crossed a threshold of movement after | |
| 120 // mouse-down when we should begin a drag. Else NO. | |
| 121 - (BOOL)hasCrossedDragThreshold:(NSEvent*)theEvent { | |
| 122 NSPoint currentLocation = [theEvent locationInWindow]; | |
| 123 if ((abs(currentLocation.x - initialMouseDownLocation_.x) > | |
| 124 kWebDragStartHysteresisX) || | |
| 125 (abs(currentLocation.y - initialMouseDownLocation_.y) > | |
| 126 kWebDragStartHysteresisY)) { | |
| 127 return YES; | |
| 128 } else { | |
| 129 return NO; | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 - (void)mouseDragged:(NSEvent*)theEvent { | |
| 134 if (beingDragged_) { | |
| 135 [super mouseDragged:theEvent]; | |
| 136 } else if (draggable_ && mayDragStart_ && | |
| 137 [self hasCrossedDragThreshold:theEvent]) { | |
| 138 [self beginDrag:theEvent]; | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 @end | 66 @end |
| 143 | 67 |
| 144 @implementation BookmarkButton(Private) | 68 @implementation BookmarkButton(Private) |
| 145 | 69 |
| 146 - (NSImage*)dragImage { | 70 - (NSImage*)dragImage { |
| 147 NSRect bounds = [self bounds]; | 71 NSRect bounds = [self bounds]; |
| 148 | 72 |
| 149 // Grab the image from the screen and put it in an |NSImage|. We can't use | 73 // Grab the image from the screen and put it in an |NSImage|. We can't use |
| 150 // this directly since we need to clip it and set its opacity. This won't work | 74 // this directly since we need to clip it and set its opacity. This won't work |
| 151 // if the source view is clipped. Fortunately, we don't display clipped | 75 // if the source view is clipped. Fortunately, we don't display clipped |
| (...skipping 18 matching lines...) Expand all Loading... |
| 170 [image drawAtPoint:NSMakePoint(0, 0) | 94 [image drawAtPoint:NSMakePoint(0, 0) |
| 171 fromRect:NSMakeRect(0, 0, NSWidth(bounds), NSHeight(bounds)) | 95 fromRect:NSMakeRect(0, 0, NSWidth(bounds), NSHeight(bounds)) |
| 172 operation:NSCompositeSourceOver | 96 operation:NSCompositeSourceOver |
| 173 fraction:kDragImageOpacity]; | 97 fraction:kDragImageOpacity]; |
| 174 | 98 |
| 175 [dragImage unlockFocus]; | 99 [dragImage unlockFocus]; |
| 176 return dragImage; | 100 return dragImage; |
| 177 } | 101 } |
| 178 | 102 |
| 179 @end // @implementation BookmarkButton(Private) | 103 @end // @implementation BookmarkButton(Private) |
| OLD | NEW |