Index: chrome/browser/cocoa/extensions/browser_actions_controller.mm |
=================================================================== |
--- chrome/browser/cocoa/extensions/browser_actions_controller.mm (revision 42818) |
+++ chrome/browser/cocoa/extensions/browser_actions_controller.mm (working copy) |
@@ -4,6 +4,7 @@ |
#import "browser_actions_controller.h" |
+#include <cmath> |
#include <string> |
#include "app/resource_bundle.h" |
@@ -59,7 +60,7 @@ |
// Useful in the case of a Browser Action being added/removed from the middle of |
// the container, this method repositions each button according to the current |
// toolbar model. |
-- (void)repositionActionButtons; |
+- (void)repositionActionButtonsAndAnimate:(BOOL)animate; |
// During container resizing, buttons become more transparent as they are pushed |
// off the screen. This method updates each button's opacity determined by the |
// position of the button. |
@@ -90,7 +91,17 @@ |
// Updates the image associated with the button should it be within the chevron |
// menu. |
- (void)actionButtonUpdated:(NSNotification*)notification; |
- |
+// Adjusts the position of the surrounding action buttons depending on where the |
+// button is within the container. |
+- (void)actionButtonDragging:(NSNotification*)notification; |
+// Updates the underlying toolbar model and "snaps" the button into its proper |
+// place within the button grid. |
+- (void)actionButtonDragFinished:(NSNotification*)notification; |
+// Moves the given button both visually and within the toolbar model to the |
+// specified index. |
+- (void)moveButton:(BrowserActionButton*)button |
+ toIndex:(NSUInteger)index |
+ animate:(BOOL)animate; |
// Handles when the given BrowserActionButton object is clicked. |
- (void)browserActionClicked:(BrowserActionButton*)button; |
// Returns whether the given extension should be displayed. Only displays |
@@ -424,7 +435,18 @@ |
[self updateOverflowMenu]; |
} |
- [self repositionActionButtons]; |
+ [[NSNotificationCenter defaultCenter] |
+ addObserver:self |
+ selector:@selector(actionButtonDragging:) |
+ name:kBrowserActionButtonDraggingNotification |
+ object:newButton]; |
+ [[NSNotificationCenter defaultCenter] |
+ addObserver:self |
+ selector:@selector(actionButtonDragFinished:) |
+ name:kBrowserActionButtonDragEndNotification |
+ object:newButton]; |
+ |
+ [self repositionActionButtonsAndAnimate:NO]; |
[containerView_ setMaxWidth: |
[self containerWidthWithButtonCount:[self buttonCount]]]; |
[containerView_ setNeedsDisplay:YES]; |
@@ -455,28 +477,24 @@ |
// No more buttons? Hide the container. |
[containerView_ setHidden:YES]; |
} else { |
- [self repositionActionButtons]; |
+ [self repositionActionButtonsAndAnimate:NO]; |
} |
[containerView_ setMaxWidth: |
[self containerWidthWithButtonCount:[self buttonCount]]]; |
[containerView_ setNeedsDisplay:YES]; |
} |
-- (void)repositionActionButtons { |
+- (void)repositionActionButtonsAndAnimate:(BOOL)animate { |
NSUInteger i = 0; |
for (ExtensionList::iterator iter = toolbarModel_->begin(); |
iter != toolbarModel_->end(); ++iter) { |
if (![self shouldDisplayBrowserAction:*iter]) |
continue; |
- |
- CGFloat xOffset = kGrippyXOffset + |
- (i * (kBrowserActionWidth + kBrowserActionButtonPadding)); |
BrowserActionButton* button = [self buttonForExtension:(*iter)]; |
if (!button) |
continue; |
- NSRect buttonFrame = [button frame]; |
- buttonFrame.origin.x = xOffset; |
- [button setFrame:buttonFrame]; |
+ if (![button isBeingDragged]) |
+ [self moveButton:button toIndex:i animate:animate]; |
++i; |
} |
} |
@@ -587,6 +605,49 @@ |
[item setImage:[button compositedImage]]; |
} |
+- (void)actionButtonDragging:(NSNotification*)notification { |
+ if (![self chevronIsHidden]) |
+ [self setChevronHidden:YES inFrame:[containerView_ frame] animate:YES]; |
+ |
+ // Determine what index the dragged button should lie in, alter the model and |
+ // reposition the buttons. |
+ CGFloat dragThreshold = std::floor(kBrowserActionWidth / 2); |
+ BrowserActionButton* draggedButton = [notification object]; |
+ NSRect draggedButtonFrame = [draggedButton frame]; |
+ |
+ NSUInteger index = 0; |
+ for (ExtensionList::iterator iter = toolbarModel_->begin(); |
+ iter != toolbarModel_->end(); ++iter) { |
+ BrowserActionButton* button = [self buttonForExtension:(*iter)]; |
+ CGFloat intersectionWidth = |
+ NSWidth(NSIntersectionRect(draggedButtonFrame, [button frame])); |
+ |
+ if (intersectionWidth > dragThreshold && button != draggedButton && |
+ ![button isAnimating]) { |
+ toolbarModel_->MoveBrowserAction([draggedButton extension], index); |
+ [self repositionActionButtonsAndAnimate:YES]; |
+ return; |
+ } |
+ ++index; |
+ } |
+} |
+ |
+- (void)actionButtonDragFinished:(NSNotification*)notification { |
+ [self showChevronIfNecessaryInFrame:[containerView_ frame] animate:YES]; |
+ DCHECK(![[notification object] isBeingDragged]); |
+ [self repositionActionButtonsAndAnimate:YES]; |
+} |
+ |
+- (void)moveButton:(BrowserActionButton*)button |
+ toIndex:(NSUInteger)index |
+ animate:(BOOL)animate { |
+ CGFloat xOffset = kGrippyXOffset + |
+ (index * (kBrowserActionWidth + kBrowserActionButtonPadding)); |
+ NSRect buttonFrame = [button frame]; |
+ buttonFrame.origin.x = xOffset; |
+ [button setFrame:buttonFrame animate:animate]; |
+} |
+ |
- (void)browserActionClicked:(BrowserActionButton*)button { |
int tabId = [self currentTabId]; |
if (tabId < 0) { |
@@ -669,7 +730,7 @@ |
nil]; |
} |
[chevronAnimation_ setViewAnimations: |
- [NSArray arrayWithObjects:animationDictionary, nil]]; |
+ [NSArray arrayWithObject:animationDictionary]]; |
[chevronAnimation_ startAnimation]; |
} |