Index: chrome/browser/cocoa/toolbar_controller.mm |
=================================================================== |
--- chrome/browser/cocoa/toolbar_controller.mm (revision 41123) |
+++ chrome/browser/cocoa/toolbar_controller.mm (working copy) |
@@ -60,21 +60,25 @@ |
// Height of the toolbar in pixels when the bookmark bar is closed. |
const CGFloat kBaseToolbarHeight = 36.0; |
-// The threshold width in pixels between the reload button (the home button is |
-// optional) and the right side of the window for use in determining whether to |
-// show or hide Browser Action buttons depending on window size. |
-const CGFloat kHideBrowserActionThresholdWidth = 300.0; |
+// The distance from the 'Go' button to the Browser Actions container in pixels. |
+const CGFloat kBrowserActionsContainerLeftPadding = 5.0; |
+// The minimum width of the location bar in pixels. |
+const CGFloat kMinimumLocationBarWidth = 100.0; |
+ |
} // namespace |
@interface ToolbarController(Private) |
- (void)addAccessibilityDescriptions; |
-- (void)windowResized; |
- (void)initCommandStatus:(CommandUpdater*)commands; |
- (void)prefChanged:(std::wstring*)prefName; |
- (BackgroundGradientView*)backgroundGradientView; |
-- (void)showOrHideBrowserActionButtons; |
-- (void)browserActionsChanged; |
+- (void)toolbarFrameChanged; |
+- (void)pinGoButtonToLeftOfBrowserActionsContainer; |
+- (void)maintainMinimumLocationBarWidth; |
+- (void)adjustBrowserActionsContainerForNewWindow; |
+- (void)browserActionsContainerDragged; |
+- (void)browserActionsVisibilityChanged; |
- (void)adjustLocationAndGoPositionsBy:(CGFloat)dX; |
@end |
@@ -217,11 +221,6 @@ |
commands_, toolbarModel_, |
profile_, browser_)); |
[locationBar_ setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; |
- [[NSNotificationCenter defaultCenter] |
- addObserver:self |
- selector:@selector(windowResized) |
- name:NSWindowDidResizeNotification |
- object:[[self view] window]]; |
// Register pref observers for the optional home and page/options buttons |
// and then add them to the toolbar based on those prefs. |
prefObserver_.reset(new ToolbarControllerInternal::PrefObserverBridge(self)); |
@@ -241,17 +240,7 @@ |
initWithBrowser:browser_ |
modelType:BACK_FORWARD_MENU_TYPE_FORWARD |
button:forwardButton_]); |
- browserActionsController_.reset([[BrowserActionsController alloc] |
- initWithBrowser:browser_ |
- containerView:browserActionsContainerView_]); |
- // When new browser actions are added/removed, the container view for them is |
- // resized, necessitating the probable resizing of surrounding elements |
- // handled by this controller. |
- [[NSNotificationCenter defaultCenter] |
- addObserver:self |
- selector:@selector(browserActionsChanged) |
- name:kBrowserActionsChangedNotification |
- object:browserActionsController_]; |
+ |
// For a popup window, the toolbar is really just a location bar |
// (see override for [ToolbarController view], below). When going |
// fullscreen, we remove the toolbar controller's view from the view |
@@ -269,11 +258,21 @@ |
NSTrackingActiveAlways |
owner:self |
userInfo:nil]); |
- [[self view] addTrackingArea:trackingArea_.get()]; |
+ NSView* toolbarView = [self view]; |
+ [toolbarView addTrackingArea:trackingArea_.get()]; |
// We want a dynamic tooltip on the go button, so tell the go button to ask |
// us for the tooltip. |
[goButton_ addToolTipRect:[goButton_ bounds] owner:self userData:nil]; |
+ |
+ // If the user has any Browser Actions installed, the container view for them |
+ // may have to be resized depending on the width of the toolbar frame. |
+ [toolbarView setPostsFrameChangedNotifications:YES]; |
+ [[NSNotificationCenter defaultCenter] |
+ addObserver:self |
+ selector:@selector(toolbarFrameChanged) |
+ name:NSViewFrameDidChangeNotification |
+ object:toolbarView]; |
} |
- (void)addAccessibilityDescriptions { |
@@ -316,12 +315,6 @@ |
forAttribute:NSAccessibilityDescriptionAttribute]; |
} |
-- (void)windowResized { |
- // Some Browser Action buttons may have to be hidden or shown depending on the |
- // window's size. |
- [self showOrHideBrowserActionButtons]; |
-} |
- |
- (void)mouseExited:(NSEvent*)theEvent { |
[[hoveredButton_ cell] setMouseInside:NO animate:YES]; |
[hoveredButton_ release]; |
@@ -599,72 +592,121 @@ |
} |
- (void)createBrowserActionButtons { |
- [browserActionsController_ createButtons]; |
- [self showOrHideBrowserActionButtons]; |
+ if (browserActionsController_.get() == nil) { |
+ browserActionsController_.reset([[BrowserActionsController alloc] |
+ initWithBrowser:browser_ |
+ containerView:browserActionsContainerView_]); |
+ [[NSNotificationCenter defaultCenter] |
+ addObserver:self |
+ selector:@selector(browserActionsContainerDragged) |
+ name:kBrowserActionGrippyDraggingNotification |
+ object:browserActionsController_]; |
+ [[NSNotificationCenter defaultCenter] |
+ addObserver:self |
+ selector:@selector(browserActionsVisibilityChanged) |
+ name:kBrowserActionVisibilityChangedNotification |
+ object:browserActionsController_]; |
+ [[NSNotificationCenter defaultCenter] |
+ addObserver:self |
+ selector:@selector(adjustBrowserActionsContainerForNewWindow) |
+ name:NSWindowDidBecomeKeyNotification |
+ object:[[self view] window]]; |
+ } |
+ |
+ CGFloat dX = NSWidth([browserActionsContainerView_ frame]) * -1; |
+ [self adjustLocationAndGoPositionsBy:dX]; |
BOOL rightBorderShown = !([pageButton_ isHidden] && [wrenchButton_ isHidden]); |
[browserActionsContainerView_ setRightBorderShown:rightBorderShown]; |
} |
-- (void)showOrHideBrowserActionButtons { |
- // TODO(andybons): This is ugly as sin and hard to follow. Fix it up. |
+- (void)adjustBrowserActionsContainerForNewWindow { |
+ [self toolbarFrameChanged]; |
+ [[NSNotificationCenter defaultCenter] |
+ removeObserver:self |
+ name:NSWindowDidBecomeKeyNotification |
+ object:[[self view] window]]; |
+} |
- int buttonCount = [browserActionsController_ buttonCount]; |
- if (buttonCount == 0 || !hasToolbar_) |
- return; |
+- (void)browserActionsContainerDragged { |
+ CGFloat locationBarWidth = NSWidth([locationBar_ frame]); |
+ locationBarAtMinSize_ = locationBarWidth <= kMinimumLocationBarWidth; |
+ [browserActionsContainerView_ setCanDragLeft:!locationBarAtMinSize_]; |
+ [browserActionsContainerView_ setGrippyPinned:locationBarAtMinSize_]; |
- CGFloat curWidth = NSWidth([[[self view] window] frame]); |
- NSRect reloadFrame = [reloadButton_ frame]; |
- // Calculate the width between the reload button and the end of the frame and |
- // subtract the threshold width, which represents the space that the |
- // (optional) home button, omnibar, go button and page/wrench buttons take up |
- // when no Browser Actions are displayed. This is to prevent the Browser |
- // Action buttons from pushing the elements to the left of them too far over. |
- CGFloat availableWidth = std::max(0.0f, |
- curWidth - reloadFrame.origin.x + NSWidth(reloadFrame) - |
- kHideBrowserActionThresholdWidth); |
- // How many Browser Action buttons can we safely display without overflow? |
- int numAvailableSlots = availableWidth / |
- (kBrowserActionWidth + kBrowserActionButtonPadding); |
- int visibleCount = [browserActionsController_ visibleButtonCount]; |
+ [self adjustLocationAndGoPositionsBy: |
+ [browserActionsContainerView_ resizeDeltaX]]; |
+} |
- // |delta| is the number of buttons that should be shown or hidden based on |
- // the number of available slots and the number of visible buttons. |
- int delta = numAvailableSlots - visibleCount; |
- BOOL hide = delta < 0; |
- if (hide) { |
- delta *= -1; |
- } else if (visibleCount == buttonCount) { |
- // The number of available slots is greater than the number of displayed |
- // buttons then all buttons are already displayed. |
- return; |
+- (void)browserActionsVisibilityChanged { |
+ [self pinGoButtonToLeftOfBrowserActionsContainer]; |
+} |
+ |
+- (void)pinGoButtonToLeftOfBrowserActionsContainer { |
+ NSRect goFrame = [goButton_ frame]; |
+ NSRect containerFrame = [browserActionsContainerView_ frame]; |
+ CGFloat leftPadding = containerFrame.origin.x - |
+ (goFrame.origin.x + NSWidth(goFrame)); |
+ if (leftPadding != kBrowserActionsContainerLeftPadding) { |
+ CGFloat dX = leftPadding - kBrowserActionsContainerLeftPadding; |
+ [self adjustLocationAndGoPositionsBy:dX]; |
} |
- int arrayOffset = hide ? -1 : 0; |
+} |
- while (delta > 0) { |
- visibleCount = [browserActionsController_ visibleButtonCount]; |
- if (visibleCount == buttonCount && !hide) |
- return; |
- BrowserActionButton* button = [[browserActionsContainerView_ subviews] |
- objectAtIndex:visibleCount + arrayOffset]; |
- [button setHidden:hide]; |
- [self browserActionsChanged]; |
- --delta; |
+- (void)maintainMinimumLocationBarWidth { |
+ CGFloat locationBarWidth = NSWidth([locationBar_ frame]); |
+ locationBarAtMinSize_ = locationBarWidth <= kMinimumLocationBarWidth; |
+ if (locationBarAtMinSize_) { |
+ CGFloat dX = kMinimumLocationBarWidth - locationBarWidth; |
+ [self adjustLocationAndGoPositionsBy:dX]; |
} |
} |
-- (void)browserActionsChanged { |
- CGFloat width = [browserActionsController_ idealContainerWidth]; |
- NSRect containerFrame = [browserActionsContainerView_ frame]; |
- CGFloat dX = containerFrame.size.width - width; |
- containerFrame.size.width = width; |
+- (void)toolbarFrameChanged { |
+ [self maintainMinimumLocationBarWidth]; |
- [browserActionsContainerView_ setFrame:NSOffsetRect(containerFrame, dX, 0)]; |
- [self adjustLocationAndGoPositionsBy:dX]; |
+ if (locationBarAtMinSize_) { |
+ // Once the grippy is pinned, leave it until it is explicity un-pinned. |
+ [browserActionsContainerView_ setGrippyPinned:YES]; |
+ NSRect containerFrame = [browserActionsContainerView_ frame]; |
+ // Determine how much the container needs to move in case it's overlapping |
+ // with the location bar. |
+ CGFloat dX = ([goButton_ frame].origin.x + NSWidth([goButton_ frame])) - |
+ containerFrame.origin.x + kBrowserActionsContainerLeftPadding; |
+ containerFrame = NSOffsetRect(containerFrame, dX, 0); |
+ containerFrame.size.width -= dX; |
+ [browserActionsContainerView_ setFrame:containerFrame]; |
+ } else if (!locationBarAtMinSize_ && |
+ [browserActionsContainerView_ grippyPinned]) { |
+ // Expand out the container until it hits the saved size, then unpin the |
+ // grippy. |
+ // Add 0.1 pixel so that it doesn't hit the minimum width codepath above. |
+ CGFloat dX = NSWidth([locationBar_ frame]) - |
+ (kMinimumLocationBarWidth + 0.1); |
+ NSRect containerFrame = [browserActionsContainerView_ frame]; |
+ containerFrame = NSOffsetRect(containerFrame, -dX, 0); |
+ containerFrame.size.width += dX; |
+ CGFloat savedContainerWidth = [browserActionsController_ savedWidth]; |
+ if (NSWidth(containerFrame) >= savedContainerWidth) { |
+ containerFrame = NSOffsetRect(containerFrame, |
+ NSWidth(containerFrame) - savedContainerWidth, 0); |
+ containerFrame.size.width = savedContainerWidth; |
+ [browserActionsContainerView_ setGrippyPinned:NO]; |
+ } |
+ [browserActionsContainerView_ setFrame:containerFrame]; |
+ [self pinGoButtonToLeftOfBrowserActionsContainer]; |
+ } |
} |
- (void)adjustLocationAndGoPositionsBy:(CGFloat)dX { |
+ // Ensure that the 'Go' button is in its proper place. |
+ NSRect goFrame = [goButton_ frame]; |
+ NSRect locationFrame = [locationBar_ frame]; |
+ CGFloat rightDelta = (locationFrame.origin.x + NSWidth(locationFrame)) - |
+ goFrame.origin.x; |
+ if (rightDelta != 0.0) |
+ [goButton_ setFrame:NSOffsetRect(goFrame, rightDelta, 0)]; |
+ |
[goButton_ setFrame:NSOffsetRect([goButton_ frame], dX, 0)]; |
- NSRect locationFrame = [locationBar_ frame]; |
locationFrame.size.width += dX; |
[locationBar_ setFrame:locationFrame]; |
} |