diff options
author | andybons@chromium.org <andybons@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-26 22:31:24 +0000 |
---|---|---|
committer | andybons@chromium.org <andybons@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-26 22:31:24 +0000 |
commit | cf5889eddcb85c35e539835f137c710763f37b08 (patch) | |
tree | 763367cab82744afe511222c52657ae1863158d2 /chrome/browser/cocoa/extensions/browser_action_button.mm | |
parent | 25af92056d8145d044674e3544010e9500b78ea3 (diff) | |
download | chromium_src-cf5889eddcb85c35e539835f137c710763f37b08.zip chromium_src-cf5889eddcb85c35e539835f137c710763f37b08.tar.gz chromium_src-cf5889eddcb85c35e539835f137c710763f37b08.tar.bz2 |
[Mac] Enables drag N' drop for the buttons within the Browser Actions container. Also fixes an issue where the grippy was being shown when no Browser Actions were installed.
Known issue: You can drag the buttons outside of the container, even though they will recover by snapping back into place. This will be fixed in a further revision.
TEST=try dragging browser action buttons in order to reorder them.
BUG=26990
Review URL: http://codereview.chromium.org/1418003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42845 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cocoa/extensions/browser_action_button.mm')
-rw-r--r-- | chrome/browser/cocoa/extensions/browser_action_button.mm | 115 |
1 files changed, 106 insertions, 9 deletions
diff --git a/chrome/browser/cocoa/extensions/browser_action_button.mm b/chrome/browser/cocoa/extensions/browser_action_button.mm index d1f1681..fe456c6 100644 --- a/chrome/browser/cocoa/extensions/browser_action_button.mm +++ b/chrome/browser/cocoa/extensions/browser_action_button.mm @@ -4,6 +4,9 @@ #import "chrome/browser/cocoa/extensions/browser_action_button.h" +#include <algorithm> +#include <cmath> + #include "base/sys_string_conversions.h" #include "chrome/browser/cocoa/extensions/extension_action_context_menu.h" #include "chrome/browser/extensions/image_loading_tracker.h" @@ -16,10 +19,16 @@ #include "gfx/rect.h" #include "gfx/size.h" #include "skia/ext/skia_utils_mac.h" +#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" extern const NSString* kBrowserActionButtonUpdatedNotification = @"BrowserActionButtonUpdatedNotification"; +extern const NSString* kBrowserActionButtonDraggingNotification = + @"BrowserActionButtonDraggingNotification"; +extern const NSString* kBrowserActionButtonDragEndNotification = + @"BrowserActionButtonDragEndNotification"; + static const CGFloat kBrowserActionBadgeOriginYOffset = 5; // Since the container is the maximum height of the toolbar, we have to move the @@ -32,6 +41,7 @@ static const CGFloat kBrowserActionHeight = 27; extern const CGFloat kBrowserActionWidth = 29; namespace { +const CGFloat kAnimationDuration = 0.2; const CGFloat kShadowOffset = 2.0; } // anonymous namespace @@ -93,8 +103,16 @@ class ExtensionImageTrackerBridge : public NotificationObserver, - (void)drawBadgeWithinFrame:(NSRect)frame; @end +@interface BrowserActionButton(Private) +- (void)endDrag; +@end + @implementation BrowserActionButton +@synthesize isBeingDragged = isBeingDragged_; +@synthesize extension = extension_; +@synthesize tabId = tabId_; + + (Class)cellClass { return [BrowserActionCell class]; } @@ -128,12 +146,90 @@ class ExtensionImageTrackerBridge : public NotificationObserver, extension_ = extension; imageLoadingBridge_.reset(new ExtensionImageTrackerBridge(self, extension)); + moveAnimation_.reset([[NSViewAnimation alloc] init]); + [moveAnimation_ gtm_setDuration:kAnimationDuration + eventMask:NSLeftMouseDownMask]; + [moveAnimation_ setAnimationBlockingMode:NSAnimationNonblocking]; + [self updateState]; } return self; } +- (BOOL)acceptsFirstResponder { + return YES; +} + +- (void)mouseDown:(NSEvent*)theEvent { + [[self cell] setHighlighted:YES]; +} + +- (void)mouseDragged:(NSEvent*)theEvent { + if (!isBeingDragged_) { + // The start of a drag. Position the button above all others. + [[self superview] addSubview:self positioned:NSWindowAbove relativeTo:nil]; + } + isBeingDragged_ = YES; + NSPoint location = [self convertPoint:[theEvent locationInWindow] + fromView:nil]; + NSRect buttonFrame = [self frame]; + // TODO(andybons): Constrain the buttons to be within the container. + // Clamp the button to be within its superview along the X-axis. + buttonFrame.origin.x += [theEvent deltaX]; + [self setFrame:buttonFrame]; + [self setNeedsDisplay:YES]; + [[NSNotificationCenter defaultCenter] + postNotificationName:kBrowserActionButtonDraggingNotification + object:self]; +} + +- (void)mouseUp:(NSEvent*)theEvent { + // There are non-drag cases where a mouseUp: may happen + // (e.g. mouse-down, cmd-tab to another application, move mouse, + // mouse-up). + NSPoint location = [self convertPoint:[theEvent locationInWindow] + fromView:nil]; + if (NSPointInRect(location, [self bounds]) && !isBeingDragged_) { + // Only perform the click if we didn't drag the button. + [self performClick:self]; + } else { + // Make sure an ESC to end a drag doesn't trigger 2 endDrags. + if (isBeingDragged_) { + [self endDrag]; + } else { + [super mouseUp:theEvent]; + } + } +} + +- (void)endDrag { + isBeingDragged_ = NO; + [[NSNotificationCenter defaultCenter] + postNotificationName:kBrowserActionButtonDragEndNotification + object:self]; + [[self cell] setHighlighted:NO]; +} + +- (void)setFrame:(NSRect)frameRect animate:(BOOL)animate { + if (!animate) { + [self setFrame:frameRect]; + } else { + if ([moveAnimation_ isAnimating]) + [moveAnimation_ stopAnimation]; + + NSDictionary* animationDictionary = + [NSDictionary dictionaryWithObjectsAndKeys: + self, NSViewAnimationTargetKey, + [NSValue valueWithRect:[self frame]], NSViewAnimationStartFrameKey, + [NSValue valueWithRect:frameRect], NSViewAnimationEndFrameKey, + nil]; + [moveAnimation_ setViewAnimations: + [NSArray arrayWithObject:animationDictionary]]; + [moveAnimation_ startAnimation]; + } +} + - (void)setDefaultIcon:(NSImage*)image { defaultIcon_.reset([image retain]); } @@ -170,12 +266,16 @@ class ExtensionImageTrackerBridge : public NotificationObserver, object:self]; } +- (BOOL)isAnimating { + return [moveAnimation_ isAnimating]; +} + - (NSImage*)compositedImage { NSRect bounds = NSMakeRect(0, 0, kBrowserActionWidth, kBrowserActionHeight); NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:NSWidth(bounds) - pixelsHigh:NSWidth(bounds) + pixelsHigh:NSHeight(bounds) bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES @@ -197,8 +297,8 @@ class ExtensionImageTrackerBridge : public NotificationObserver, // TODO(andybons): Figure out why |flipped| can be yes in certain cases. // http://crbug.com/38943 [actionImage setFlipped:NO]; - CGFloat xPos = floor((NSWidth(bounds) - [actionImage size].width) / 2); - CGFloat yPos = floor((NSHeight(bounds) - [actionImage size].height) / 2); + CGFloat xPos = std::floor((NSWidth(bounds) - [actionImage size].width) / 2); + CGFloat yPos = std::floor((NSHeight(bounds) - [actionImage size].height) / 2); [actionImage drawAtPoint:NSMakePoint(xPos, yPos) fromRect:NSZeroRect operation:NSCompositeSourceOver @@ -215,13 +315,13 @@ class ExtensionImageTrackerBridge : public NotificationObserver, return compositeImage; } -@synthesize tabId = tabId_; -@synthesize extension = extension_; - @end @implementation BrowserActionCell +@synthesize tabId = tabId_; +@synthesize extensionAction = extensionAction_; + - (void)setIconShadow { // Create the shadow below and to the right of the drawn image. scoped_nsobject<NSShadow> imgShadow([[NSShadow alloc] init]); @@ -248,7 +348,4 @@ class ExtensionImageTrackerBridge : public NotificationObserver, [NSGraphicsContext restoreGraphicsState]; } -@synthesize tabId = tabId_; -@synthesize extensionAction = extensionAction_; - @end |