summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-14 01:01:17 +0000
committerviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-14 01:01:17 +0000
commit919905ddd11db90bf0b4a03f9b3e79b9c289aa04 (patch)
treee5586bbcff8540fdb241845f7f7e075fc33ad996 /chrome/browser
parent0207043ab2d23d96a700bcb9bfb9044bd240ae7b (diff)
downloadchromium_src-919905ddd11db90bf0b4a03f9b3e79b9c289aa04.zip
chromium_src-919905ddd11db90bf0b4a03f9b3e79b9c289aa04.tar.gz
chromium_src-919905ddd11db90bf0b4a03f9b3e79b9c289aa04.tar.bz2
Mac: Animate the bookmark bar showing/hiding.
There's a huge refactoring of the bookmark bar controller in this CL, so that animation-related code is in only a few places (instead of scattered all over the place). Changes to BookmarkBar.xib: Since BookmarkBarToolbarView now inherits from AnimatableView, I had to hook up its delegate_ member to File's Owner (i.e., the BookmarkBarController). Not yet implemented: morphing between the detached bar (on the NTP) and anything else. BUG=25600 TEST=Go to a normal page, show/hide the bookmark bar (Shift-Cmd-B), watch it animate. Review URL: http://codereview.chromium.org/384105 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31977 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser.h4
-rw-r--r--chrome/browser/cocoa/animatable_view.h3
-rw-r--r--chrome/browser/cocoa/bookmark_bar_bridge_unittest.mm2
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller.h108
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller.mm396
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller_unittest.mm130
-rw-r--r--chrome/browser/cocoa/bookmark_bar_toolbar_view.h11
-rw-r--r--chrome/browser/cocoa/bookmark_bar_toolbar_view.mm10
-rw-r--r--chrome/browser/cocoa/bookmark_bar_toolbar_view_unittest.mm29
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.mm2
-rw-r--r--chrome/browser/cocoa/browser_window_controller.h6
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm150
-rw-r--r--chrome/browser/cocoa/browser_window_controller_unittest.mm3
-rw-r--r--chrome/browser/cocoa/toolbar_compressable.h19
-rw-r--r--chrome/browser/cocoa/toolbar_controller.h15
-rw-r--r--chrome/browser/cocoa/toolbar_controller.mm20
-rw-r--r--chrome/browser/cocoa/toolbar_controller_unittest.mm13
-rw-r--r--chrome/browser/cocoa/view_resizer_pong.mm3
18 files changed, 631 insertions, 293 deletions
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h
index a587aff..243b464 100644
--- a/chrome/browser/browser.h
+++ b/chrome/browser/browser.h
@@ -712,10 +712,10 @@ class Browser : public TabStripModelDelegate,
NotificationRegistrar registrar_;
// This Browser's type.
- Type type_;
+ const Type type_;
// This Browser's profile.
- Profile* profile_;
+ Profile* const profile_;
// This Browser's window.
BrowserWindow* window_;
diff --git a/chrome/browser/cocoa/animatable_view.h b/chrome/browser/cocoa/animatable_view.h
index ef35eb7..aa8f01d 100644
--- a/chrome/browser/cocoa/animatable_view.h
+++ b/chrome/browser/cocoa/animatable_view.h
@@ -9,6 +9,7 @@
#import "base/cocoa_protocols_mac.h"
#include "base/scoped_nsobject.h"
+#import "chrome/browser/cocoa/background_gradient_view.h"
#import "chrome/browser/cocoa/view_resizer.h"
// A view that provides an animatable height property. Provides methods to
@@ -19,7 +20,7 @@
// animation ends normally and an |animationDidStop:| message when the animation
// was canceled (even when canceled as a result of a new animation starting).
-@interface AnimatableView : NSView<NSAnimationDelegate> {
+@interface AnimatableView : BackgroundGradientView<NSAnimationDelegate> {
@protected
IBOutlet id delegate_; // weak, used to send animation ended messages.
diff --git a/chrome/browser/cocoa/bookmark_bar_bridge_unittest.mm b/chrome/browser/cocoa/bookmark_bar_bridge_unittest.mm
index 2b03429..66d853c 100644
--- a/chrome/browser/cocoa/bookmark_bar_bridge_unittest.mm
+++ b/chrome/browser/cocoa/bookmark_bar_bridge_unittest.mm
@@ -35,7 +35,7 @@ typedef std::pair<GURL,WindowOpenDisposition> OpenInfo;
- (id)initWithBrowser:(Browser*)browser {
if ((self = [super initWithBrowser:browser
initialWidth:100 // arbitrary
- compressDelegate:nil
+ delegate:nil
resizeDelegate:nil])) {
callbacks_.reset([[NSMutableArray alloc] init]);
}
diff --git a/chrome/browser/cocoa/bookmark_bar_controller.h b/chrome/browser/cocoa/bookmark_bar_controller.h
index 0b51d4e..c390893 100644
--- a/chrome/browser/cocoa/bookmark_bar_controller.h
+++ b/chrome/browser/cocoa/bookmark_bar_controller.h
@@ -15,17 +15,16 @@
#include "chrome/browser/cocoa/tab_strip_model_observer_bridge.h"
#include "webkit/glue/window_open_disposition.h"
-@class BackgroundGradientView;
-@class BookmarkBarStateController;
+@class BookmarkBarController;
class BookmarkModel;
class BookmarkNode;
@class BookmarkBarView;
class Browser;
-@protocol ToolbarCompressable;
class GURL;
@class MenuButton;
class Profile;
class PrefService;
+class TabContents;
@class ToolbarController;
@protocol ViewResizer;
@@ -40,19 +39,57 @@ const CGFloat kNoBookmarksHorizontalOffset = 5.0;
const CGFloat kNoBookmarksVerticalOffset = 22.0;
const CGFloat kNoBookmarksNTPVerticalOffset = 28.0;
-} // namespace
+// States for the bookmark bar.
+enum VisualState {
+ kInvalidState = 0,
+ kHiddenState = 1,
+ kShowingState = 2,
+ kDetachedState = 3,
+};
+
+} // namespace bookmarks
+
+// The interface for the bookmark bar controller's delegate. Currently, the
+// delegate is the BWC and is responsible for ensuring that the toolbar is
+// displayed correctly (as specified by |-getDesiredToolbarHeightCompression|
+// and |-shouldToolbarShowDivider|) at the beginning and at the end of an
+// animation (or after a state change).
+@protocol BookmarkBarControllerDelegate
+
+// Sent when the state has changed (after any animation), but before the final
+// display update.
+- (void)bookmarkBar:(BookmarkBarController*)controller
+ didChangeFromState:(bookmarks::VisualState)oldState
+ toState:(bookmarks::VisualState)newState;
+
+// Sent before the animation begins.
+- (void)bookmarkBar:(BookmarkBarController*)controller
+willAnimateFromState:(bookmarks::VisualState)oldState
+ toState:(bookmarks::VisualState)newState;
+
+@end
// A controller for the bookmark bar in the browser window. Handles showing
// and hiding based on the preference in the given profile.
@interface BookmarkBarController :
- NSViewController<BookmarkBarToolbarViewController> {
+ NSViewController<BookmarkBarToolbarViewController> {
@private
+ // The visual state of the bookmark bar. If an animation is running, this is
+ // set to the "destination" and |lastVisualState_| is set to the "original"
+ // state. This is set to |kInvalidState| on initialization (when the
+ // appropriate state is not yet known).
+ bookmarks::VisualState visualState_;
+
+ // The "original" state of the bookmark bar if an animation is running,
+ // otherwise it should be |kInvalidState|.
+ bookmarks::VisualState lastVisualState_;
+
Browser* browser_; // weak; owned by its window
BookmarkModel* bookmarkModel_; // weak; part of the profile owned by the
// top-level Browser object.
// Our initial view width, which is applied in awakeFromNib.
- float initialWidth_;
+ CGFloat initialWidth_;
// BookmarkNodes have a 64bit id. NSMenuItems have a 32bit tag used
// to represent the bookmark node they refer to. This map provides
@@ -78,16 +115,12 @@ const CGFloat kNoBookmarksNTPVerticalOffset = 28.0;
// BookmarkModelObserver)
scoped_ptr<BookmarkBarBridge> bridge_;
- // Delegate that is alerted about whether it should be compressed because
- // it's right next to us.
- id<ToolbarCompressable> compressDelegate_; // weak
+ // Delegate that is informed about state changes in the bookmark bar.
+ id<BookmarkBarControllerDelegate> delegate_; // weak
// Delegate that can resize us.
id<ViewResizer> resizeDelegate_; // weak
- // Lets us get TabSelectedAt notifications.
- scoped_ptr<TabStripModelObserverBridge> tabObserver_;
-
IBOutlet BookmarkBarView* buttonView_;
IBOutlet MenuButton* offTheSideButton_; // aka the chevron
IBOutlet NSMenu* buttonContextMenu_;
@@ -96,22 +129,24 @@ const CGFloat kNoBookmarksNTPVerticalOffset = 28.0;
scoped_nsobject<NSButton> otherBookmarksButton_;
}
+@property(readonly, nonatomic) bookmarks::VisualState visualState;
+@property(readonly, nonatomic) bookmarks::VisualState lastVisualState;
+@property(assign, nonatomic) id<BookmarkBarControllerDelegate> delegate;
+
// Initializes the bookmark bar controller with the given browser
// profile and delegates.
- (id)initWithBrowser:(Browser*)browser
- initialWidth:(float)initialWidth
- compressDelegate:(id<ToolbarCompressable>)compressDelegate
+ initialWidth:(CGFloat)initialWidth
+ delegate:(id<BookmarkBarControllerDelegate>)delegate
resizeDelegate:(id<ViewResizer>)resizeDelegate;
-// Returns the backdrop to the bookmark bar.
-- (BackgroundGradientView*)backgroundGradientView;
+// Updates the bookmark bar (from its current, possibly in-transition) state to
+// the one appropriate for the new conditions.
+- (void)updateAndShowNormalBar:(BOOL)showNormalBar
+ showDetachedBar:(BOOL)showDetachedBar
+ withAnimation:(BOOL)animate;
-// Tell the bar to show itself if needed (e.g. if the kShowBookmarkBar
-// is set). Called once after the controller is first created.
-- (void)showIfNeeded;
-
-// Update the visible state of the bookmark bar based on the current value of
-// -[BookmarkBarController isAlwaysVisible].
+// Update the visible state of the bookmark bar.
- (void)updateVisibility;
// Turn on or off the bookmark bar and prevent or reallow its
@@ -119,19 +154,27 @@ const CGFloat kNoBookmarksNTPVerticalOffset = 28.0;
// if needed. For fullscreen mode.
- (void)setBookmarkBarEnabled:(BOOL)enabled;
-// Returns YES if the bookmarks bar is currently visible, either because the
-// user has asked for it to always be visible, or because the current tab is the
-// New Tab page.
+// Returns YES if the bookmarks bar is currently visible (as a normal toolbar or
+// as a detached bar on the NTP), NO otherwise.
- (BOOL)isVisible;
-// Returns true if the bookmark bar needs to be shown currently because a tab
-// that requires it is selected. The bookmark bar will have a different
-// appearance when it is shown if isAlwaysVisible returns NO.
-- (BOOL)isNewTabPage;
+// Returns YES if an animation is currently running, NO otherwise.
+- (BOOL)isAnimationRunning;
+
+// Returns YES if the bookmarks bar is (to be) shown as part of the normal
+// toolbar, NO otherwise. This is exclusive of |-isShownAsDetachedBar|.
+- (BOOL)isShownAsToolbar;
+
+// Returns YES if the bookmarks bar is (to be) shown as a detached bar, NO
+// otherwise; required for the |BookmarkBarToolbarViewController| protocol. This
+// is exclusive of |-isShownAsToolbar|.
+- (BOOL)isShownAsDetachedBar;
-// Returns true if the bookmark bar is visible for all tabs. (This corresponds
-// to the user having selected "Always show the bookmark bar")
-- (BOOL)isAlwaysVisible;
+// Returns the amount by which the toolbar above should be compressed.
+- (CGFloat)getDesiredToolbarHeightCompression;
+
+// Returns whether or not the toolbar above should show the divider.
+- (BOOL)shouldToolbarShowDivider;
// Returns true if at least one bookmark was added.
- (BOOL)addURLs:(NSArray*)urls withTitles:(NSArray*)titles at:(NSPoint)point;
@@ -177,7 +220,6 @@ const CGFloat kNoBookmarksNTPVerticalOffset = 28.0;
node:(const BookmarkNode*)node;
@end
-
// These APIs should only be used by unit tests (or used internally).
@interface BookmarkBarController(InternalOrTestingAPI)
- (void)openURL:(GURL)url disposition:(WindowOpenDisposition)disposition;
diff --git a/chrome/browser/cocoa/bookmark_bar_controller.mm b/chrome/browser/cocoa/bookmark_bar_controller.mm
index 7a616de..3db0e8b 100644
--- a/chrome/browser/cocoa/bookmark_bar_controller.mm
+++ b/chrome/browser/cocoa/bookmark_bar_controller.mm
@@ -10,6 +10,7 @@
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
+#import "chrome/browser/cocoa/background_gradient_view.h"
#import "chrome/browser/cocoa/bookmark_bar_bridge.h"
#import "chrome/browser/cocoa/bookmark_bar_constants.h"
#import "chrome/browser/cocoa/bookmark_bar_controller.h"
@@ -35,6 +36,77 @@
#include "skia/ext/skia_utils_mac.h"
#import "third_party/mozilla/include/NSPasteboard+Utils.h"
+// Bookmark bar state changing and animations
+//
+// The bookmark bar has three real states: "showing" (a normal bar attached to
+// the toolbar), "hidden", and "detached" (pretending to be part of the web
+// content on the NTP). It can, or at least should be able to, animate between
+// these states. There are several complications even without animation:
+// - The placement of the bookmark bar is done by the BWC, and it needs to know
+// the state in order to place the bookmark bar correctly (immediately below
+// the toolbar when showing, below the infobar when detached).
+// - The "divider" (a black line) needs to be drawn by either the toolbar (when
+// the bookmark bar is hidden or detached) or by the bookmark bar (when it is
+// showing). It should not be drawn by both.
+// - The toolbar needs to vertically "compress" when the bookmark bar is
+// showing. This ensures the proper display of both the bookmark bar and the
+// toolbar, and gives a padded area around the bookmark bar items for right
+// clicks, etc.
+//
+// Our model is that the BWC controls us and also the toolbar. We try not to
+// talk to the browser nor the toolbar directly, instead centralizing control in
+// the BWC. The key method by which the BWC controls us is
+// |-updateAndShowNormalBar:showDetachedBar:withAnimation:|. This invokes state
+// changes, and at appropriate times we request that the BWC do things for us
+// via either the resize delegate or our general delegate. If the BWC needs any
+// information about what it should do, or tell the toolbar to do, it can then
+// query us back (e.g., |-isShownAs...|, |-getDesiredToolbarHeightCompression|,
+// |-shouldToolbarShowDivider|, etc.).
+//
+// Animation-related complications:
+// - Compression of the toolbar is touchy during animation. It must not be
+// compressed while the bookmark bar is animating to/from showing (from/to
+// hidden), otherwise it would look like the bookmark bar's contents are
+// sliding out of the controls inside the toolbar. As such, we have to make
+// sure that the bookmark bar is shown at the right location and at the
+// right height (at various points in time).
+// - Showing the divider is also complicated during animation between hidden
+// and showing. We have to make sure that the toolbar does not show the
+// divider despite the fact that it's not compressed. The exception to this
+// is at the beginning/end of the animation when the toolbar is still
+// uncompressed but the bookmark bar has height 0. If we're not careful, we
+// get a flicker at this point.
+// - We have to ensure that we do the right thing if we're told to change state
+// while we're running an animation. The generic/easy thing to do is to jump
+// to the end state of our current animation, and (if the new state change
+// again involves an animation) begin the new animation. We can do better
+// than that, however, and sometimes just change the current animation to go
+// to the new end state (e.g., by "reversing" the animation in the showing ->
+// hidden -> showing case). We also have to ensure that demands to
+// immediately change state are always honoured.
+//
+// Pointers to animation logic:
+// - |-moveToVisualState:withAnimation:| starts animations, deciding which ones
+// we know how to handle.
+// - |showBookmarkBarWithAnimation:| has most of the actual logic.
+// - |-getDesiredToolbarHeightCompression| and |-shouldToolbarShowDivider|
+// contain related logic.
+// - The BWC's |-layoutSubviews| needs to know how to position things.
+// - The BWC should implement |-bookmarkBar:didChangeFromState:toState:| and
+// |-bookmarkBar:willAnimateFromState:toState:| in order to inform the
+// toolbar of required changes.
+
+namespace {
+
+// Overlap (in pixels) between the toolbar and the bookmark bar (when showing in
+// normal mode).
+const CGFloat kBookmarkBarOverlap = 6.0;
+
+// Duration of the bookmark bar animations.
+const NSTimeInterval kBookmarkBarAnimationDuration = 0.12;
+
+} // namespace
+
// Specialization of NSButton that responds to middle-clicks. By default,
// NSButton ignores them.
@interface BookmarkButton : NSButton
@@ -47,7 +119,34 @@
@end
@interface BookmarkBarController(Private)
-- (void)showBookmarkBar:(BOOL)enable immediately:(BOOL)immediately;
+// Determines the appropriate state for the given situation.
++ (bookmarks::VisualState)visualStateToShowNormalBar:(BOOL)showNormalBar
+ showDetachedBar:(BOOL)showDetachedBar;
+
+// Moves to the given next state (from the current state), possibly animating.
+// If |animate| is NO, it will stop any running animation and jump to the given
+// state. If YES, it may either (depending on implementation) jump to the end of
+// the current animation and begin the next one, or stop the current animation
+// mid-flight and animate to the next state.
+- (void)moveToVisualState:(bookmarks::VisualState)nextVisualState
+ withAnimation:(BOOL)animate;
+
+// Return the backdrop to the bookmark bar as various types.
+- (BackgroundGradientView*)backgroundGradientView;
+- (AnimatableView*)animatableView;
+
+// Puts stuff into the final visual state without animating, stopping a running
+// animation if necessary.
+- (void)finalizeVisualState;
+
+// Stops any current animation in its tracks (midway).
+- (void)stopCurrentAnimation;
+
+// Show/hide the bookmark bar. Handles animating the resize of the content view.
+// if |animate| is YES, the changes are made using the animator; otherwise they
+// are made immediately.
+- (void)showBookmarkBarWithAnimation:(BOOL)animate;
+
- (void)addNode:(const BookmarkNode*)child toMenu:(NSMenu*)menu;
- (void)addFolderNode:(const BookmarkNode*)node toMenu:(NSMenu*)menu;
- (void)tagEmptyMenu:(NSMenu*)menu;
@@ -62,20 +161,27 @@
@implementation BookmarkBarController
+@synthesize visualState = visualState_;
+@synthesize lastVisualState = lastVisualState_;
+@synthesize delegate = delegate_;
+
- (id)initWithBrowser:(Browser*)browser
initialWidth:(float)initialWidth
- compressDelegate:(id<ToolbarCompressable>)compressDelegate
+ delegate:(id<BookmarkBarControllerDelegate>)delegate
resizeDelegate:(id<ViewResizer>)resizeDelegate {
if ((self = [super initWithNibName:@"BookmarkBar"
bundle:mac_util::MainAppBundle()])) {
+ // Initialize to an invalid state.
+ visualState_ = bookmarks::kInvalidState;
+ lastVisualState_ = bookmarks::kInvalidState;
+
browser_ = browser;
initialWidth_ = initialWidth;
bookmarkModel_ = browser_->profile()->GetBookmarkModel();
buttons_.reset([[NSMutableArray alloc] init]);
- compressDelegate_ = compressDelegate;
+ delegate_ = delegate;
resizeDelegate_ = resizeDelegate;
- tabObserver_.reset(
- new TabStripModelObserverBridge(browser_->tabstrip_model(), self));
+ [[self animatableView] setResizeDelegate:resizeDelegate];
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
folderImage_.reset([rb.GetNSImageNamed(IDR_BOOKMARK_BAR_FOLDER) retain]);
@@ -85,6 +191,9 @@
}
- (void)dealloc {
+ // We better stop any in-flight animation if we're being killed.
+ [[self animatableView] stopAnimation];
+
// Remove our view from its superview so it doesn't attempt to reference
// it when the controller is gone.
//TODO(dmaclach): Remove -- http://crbug.com/25845
@@ -112,8 +221,8 @@
DCHECK([offTheSideButton_ attachedMenu]);
- // To make life happier when the bookmark bar is floating, the
- // chevron is a child of the button view.
+ // To make life happier when the bookmark bar is floating, the chevron is a
+ // child of the button view.
[offTheSideButton_ removeFromSuperview];
[buttonView_ addSubview:offTheSideButton_];
@@ -127,14 +236,16 @@
object:[self view]];
}
-// Method is the same as [self view], but is provided to be explicit.
+// (Private) Method is the same as [self view], but is provided to be explicit.
- (BackgroundGradientView*)backgroundGradientView {
+ DCHECK([[self view] isKindOfClass:[BackgroundGradientView class]]);
return (BackgroundGradientView*)[self view];
}
-- (void)showIfNeeded {
- if (browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar))
- [self showBookmarkBar:YES immediately:YES];
+// (Private) Method is the same as [self view], but is provided to be explicit.
+- (AnimatableView*)animatableView {
+ DCHECK([[self view] isKindOfClass:[AnimatableView class]]);
+ return (AnimatableView*)[self view];
}
// Position the off-the-side chevron to the left of the otherBookmarks button.
@@ -185,16 +296,15 @@
NSPoint newOrigin;
newOrigin.x = parent.origin.x + bookmarks::kNoBookmarksHorizontalOffset;
newOrigin.y = parent.origin.y + parent.size.height -
- ([self isAlwaysVisible] ? bookmarks::kNoBookmarksVerticalOffset :
- bookmarks::kNoBookmarksNTPVerticalOffset);
+ ([self isShownAsToolbar] ? bookmarks::kNoBookmarksVerticalOffset :
+ bookmarks::kNoBookmarksNTPVerticalOffset);
[noItemsView setFrameOrigin:newOrigin];
}
-// Change the layout of the bookmark bar's subviews in response to a
-// visibility change (e.g. show or hide the bar) or style change
-// (attached or floating).
+// Change the layout of the bookmark bar's subviews in response to a visibility
+// change (e.g., show or hide the bar) or style change (attached or floating).
- (void)layoutSubviews {
- if ([self drawAsFloatingBar]) {
+ if (visualState_ == bookmarks::kDetachedState) {
// The internal bookmark bar should have padding to center it.
NSRect frame = [[self view] frame];
[buttonView_ setFrame:
@@ -212,49 +322,125 @@
}
}
-// Show or hide the bar based on the value of |show|. Handles animating the
-// resize of the content view. if |immediately| is YES, make changes
-// immediately instead of using an animator. The routine which enables the bar
-// will show it if relevant using other mechanisms (the pref) to determine
-// desired state.
-- (void)showBookmarkBar:(BOOL)show immediately:(BOOL)immediately {
- BOOL compressed = [self isAlwaysVisible];
- [compressDelegate_ setShouldBeCompressed:compressed];
+// (Private)
+- (void)showBookmarkBarWithAnimation:(BOOL)animate {
+ if (animate) {
+ // Animating from hidden to normal bar.
+ if (lastVisualState_ == bookmarks::kHiddenState &&
+ visualState_ == bookmarks::kShowingState) {
+ [[self backgroundGradientView] setShowsDivider:YES];
+ [[self view] setHidden:NO];
+ AnimatableView* view = [self animatableView];
+ // Height takes into account the extra height we have since the toolbar
+ // only compresses when we're done.
+ [view animateToNewHeight:([self preferredHeight] - kBookmarkBarOverlap)
+ duration:kBookmarkBarAnimationDuration];
+ return;
+ }
+
+ // Animating from normal bar to hidden.
+ if (lastVisualState_ == bookmarks::kShowingState &&
+ visualState_ == bookmarks::kHiddenState) {
+ // The toolbar uncompresses immediately at the beginning (otherwise the
+ // slide looks wrong, since we slide into the bottom of stuff in the
+ // toolbar). Do this only if we're at the beginning height since we may
+ // enter this mid-animation.
+ if (NSHeight([[self view] frame]) == bookmarks::kBookmarkBarHeight) {
+ [resizeDelegate_ resizeView:[self view]
+ newHeight:(bookmarks::kBookmarkBarHeight -
+ kBookmarkBarOverlap)];
+ }
+ [[self backgroundGradientView] setShowsDivider:YES];
+ [[self view] setHidden:NO];
+ AnimatableView* view = [self animatableView];
+ [view animateToNewHeight:0
+ duration:kBookmarkBarAnimationDuration];
+ return;
+ }
+
+ // TODO(viettrungluu): other animation cases. Note: will need to fade in/out
+ // divider when animating from/to detached bar (to/from normal bar).
+
+ // Fall through for any cases we don't know about.
+ }
+ BOOL show = [self isVisible];
CGFloat height = show ? [self preferredHeight] : 0;
[resizeDelegate_ resizeView:[self view] newHeight:height];
- [[self view] setHidden:show ? NO : YES];
- DCHECK([[self view] isKindOfClass:[BookmarkBarToolbarView class]]);
+ // Only show the divider if showing the normal bookmark bar.
+ BOOL showDivider = (visualState_ == bookmarks::kShowingState ||
+ lastVisualState_ == bookmarks::kShowingState) ? YES : NO;
+ [[self backgroundGradientView] setShowsDivider:showDivider];
+
+ // Make sure we're shown.
+ [[self view] setHidden:(show ? NO : YES)];
[self layoutSubviews];
[self frameDidChange];
}
-// We don't change a preference; we only change visibility.
-// Preference changing (global state) is handled in
-// BrowserWindowCocoa::ToggleBookmarkBar(). We simply update the visibility of
-// the bar based on the current value of the pref.
+// We don't change a preference; we only change visibility. Preference changing
+// (global state) is handled in |BrowserWindowCocoa::ToggleBookmarkBar()|. We
+// simply update based on what we're told.
- (void)updateVisibility {
- [self showBookmarkBar:[self isVisible] immediately:YES];
+ [self showBookmarkBarWithAnimation:NO];
}
- (void)setBookmarkBarEnabled:(BOOL)enabled {
- barIsEnabled_ = enabled ? YES : NO;
+ barIsEnabled_ = enabled;
[self updateVisibility];
}
- (BOOL)isVisible {
- return ([self isAlwaysVisible] && barIsEnabled_) || [self isNewTabPage];
+ return (barIsEnabled_ && (visualState_ == bookmarks::kShowingState ||
+ visualState_ == bookmarks::kDetachedState)) ?
+ YES : NO;
}
-- (BOOL)isNewTabPage {
- return browser_ && browser_->GetSelectedTabContents() &&
- browser_->GetSelectedTabContents()->ShouldShowBookmarkBar();
+- (BOOL)isAnimationRunning {
+ return (lastVisualState_ == bookmarks::kInvalidState) ? NO : YES;
}
-- (BOOL)isAlwaysVisible {
- return browser_ &&
- browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
+- (BOOL)isShownAsToolbar {
+ return (visualState_ == bookmarks::kShowingState) ? YES : NO;
+}
+
+- (BOOL)isShownAsDetachedBar {
+ return (visualState_ == bookmarks::kDetachedState) ? YES : NO;
+}
+
+- (CGFloat)getDesiredToolbarHeightCompression {
+ // Some special cases....
+ if ([self isAnimationRunning]) {
+ // No toolbar compression when animating between showing and hidden.
+ if ((lastVisualState_ == bookmarks::kHiddenState &&
+ visualState_ == bookmarks::kShowingState) ||
+ (lastVisualState_ == bookmarks::kShowingState &&
+ visualState_ == bookmarks::kHiddenState))
+ return 0;
+
+ // TODO(viettrungluu): other animation cases.
+ }
+
+ return (visualState_ == bookmarks::kShowingState) ? kBookmarkBarOverlap : 0;
+}
+
+- (BOOL)shouldToolbarShowDivider {
+ // Some special cases....
+ if ([self isAnimationRunning]) {
+ // In general, the toolbar shouldn't show a divider while we're animating
+ // between showing and hidden. The exception is when our height is < 1, in
+ // which case we can't draw it.
+ if ((lastVisualState_ == bookmarks::kHiddenState &&
+ visualState_ == bookmarks::kShowingState) ||
+ (lastVisualState_ == bookmarks::kShowingState &&
+ visualState_ == bookmarks::kHiddenState))
+ return (NSHeight([[self view] frame]) < 1) ? YES : NO;
+
+ // TODO(viettrungluu): other animation cases.
+ }
+
+ return (visualState_ == bookmarks::kShowingState) ? NO : YES;
}
- (BOOL)addURLs:(NSArray*)urls withTitles:(NSArray*)titles at:(NSPoint)point {
@@ -274,18 +460,15 @@
}
- (int)currentTabContentsHeight {
- return browser_->GetSelectedTabContents()->view()->GetContainerSize().
- height();
+ return browser_->GetSelectedTabContents() ?
+ browser_->GetSelectedTabContents()->view()->GetContainerSize().height() :
+ 0;
}
- (ThemeProvider*)themeProvider {
return browser_->profile()->GetThemeProvider();
}
-- (BOOL)drawAsFloatingBar {
- return ![self isAlwaysVisible] && [self isNewTabPage];
-}
-
// Return nil if menuItem has no delegate.
- (BookmarkNode*)nodeFromMenuItem:(id)menuItem {
NSCell* cell = reinterpret_cast<NSCell*>([[menuItem menu] delegate]);
@@ -349,27 +532,10 @@
}
- (int)preferredHeight {
- return [self isAlwaysVisible] ? bookmarks::kBookmarkBarHeight :
+ return [self isShownAsToolbar] ? bookmarks::kBookmarkBarHeight :
bookmarks::kNTPBookmarkBarHeight;
}
-- (void)selectTabWithContents:(TabContents*)newContents
- previousContents:(TabContents*)oldContents
- atIndex:(NSInteger)index
- userGesture:(bool)wasUserGesture {
- // We need selectTabWithContents: for when we change from a tab that is the
- // new tab page to a tab that isn't.
- [self updateVisibility];
-}
-
-- (void)tabChangedWithContents:(TabContents*)contents
- atIndex:(NSInteger)index
- loadingOnly:(BOOL)loading {
- // We need tabChangedWithContents: for when the user clicks a bookmark from
- // the bookmark bar on the new tab page.
- [self updateVisibility];
-}
-
// Recursively add the given bookmark node and all its children to
// menu, one menu item per node.
- (void)addNode:(const BookmarkNode*)child toMenu:(NSMenu*)menu {
@@ -934,4 +1100,106 @@
return defaultImage_;
}
+// Determines the appropriate state for the given situation.
++ (bookmarks::VisualState)visualStateToShowNormalBar:(BOOL)showNormalBar
+ showDetachedBar:(BOOL)showDetachedBar {
+ if (showNormalBar)
+ return bookmarks::kShowingState;
+ if (showDetachedBar)
+ return bookmarks::kDetachedState;
+ return bookmarks::kHiddenState;
+}
+
+- (void)moveToVisualState:(bookmarks::VisualState)nextVisualState
+ withAnimation:(BOOL)animate {
+ BOOL isAnimationRunning = [self isAnimationRunning];
+
+ // No-op if the next state is the same as the "current" one, subject to the
+ // following conditions:
+ // - no animation is running; or
+ // - an animation is running and |animate| is YES ([*] if it's NO, we'd want
+ // to cancel the animation and jump to the final state).
+ if ((nextVisualState == visualState_) && (!isAnimationRunning || animate))
+ return;
+
+ // If an animation is running, we want to finalize it. Otherwise we'd have to
+ // be able to animate starting from the middle of one type of animation. We
+ // assume that animations that we know about can be "reversed".
+ if (isAnimationRunning) {
+ // Don't cancel if we're going to reverse the animation.
+ if (nextVisualState != lastVisualState_) {
+ [self stopCurrentAnimation];
+ [self finalizeVisualState];
+ }
+
+ // If we're in case [*] above, we can stop here.
+ if (nextVisualState == visualState_)
+ return;
+ }
+
+ // Now update with the new state change.
+ lastVisualState_ = visualState_;
+ visualState_ = nextVisualState;
+
+ if (animate) {
+ // Take care of any animation cases we know how to handle.
+
+ // We know how to handle hidden <-> normal....
+ if ((lastVisualState_ == bookmarks::kHiddenState &&
+ visualState_ == bookmarks::kShowingState) ||
+ (lastVisualState_ == bookmarks::kShowingState &&
+ visualState_ == bookmarks::kHiddenState)) {
+ [delegate_ bookmarkBar:self willAnimateFromState:lastVisualState_
+ toState:visualState_];
+ [self showBookmarkBarWithAnimation:YES];
+ return;
+ }
+
+ // TODO(viettrungluu): we don't know about any yet....
+
+ // Let any animation cases which we don't know how to handle fall through to
+ // the unanimated case.
+ }
+
+ // Just jump to the state.
+ [self finalizeVisualState];
+}
+
+// N.B.: |-moveToVisualState:...| will check if this should be a no-op or not.
+- (void)updateAndShowNormalBar:(BOOL)showNormalBar
+ showDetachedBar:(BOOL)showDetachedBar
+ withAnimation:(BOOL)animate {
+ bookmarks::VisualState newVisualState =
+ [BookmarkBarController visualStateToShowNormalBar:showNormalBar
+ showDetachedBar:showDetachedBar];
+ [self moveToVisualState:newVisualState
+ withAnimation:animate];
+}
+
+// (Private)
+- (void)finalizeVisualState {
+ // We promise that our delegate that the variables will be finalized before
+ // the call to |-bookmarkBar:didChangeFromState:toState:|.
+ bookmarks::VisualState oldVisualState = lastVisualState_;
+ lastVisualState_ = bookmarks::kInvalidState;
+
+ // Notify our delegate.
+ [delegate_ bookmarkBar:self didChangeFromState:oldVisualState
+ toState:visualState_];
+
+ // Update ourselves visually.
+ [self updateVisibility];
+}
+
+// (Private)
+- (void)stopCurrentAnimation {
+ [[self animatableView] stopAnimation];
+}
+
+// Delegate method for |AnimatableView| (a superclass of
+// |BookmarkBarToolbarView|).
+- (void)animationDidEnd:(NSAnimation*)animation {
+ [self finalizeVisualState];
+}
+
@end
diff --git a/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm b/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm
index 5bfd58c..228bd68 100644
--- a/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm
+++ b/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm
@@ -12,7 +12,6 @@
#import "chrome/browser/cocoa/bookmark_bar_view.h"
#include "chrome/browser/cocoa/browser_test_helper.h"
#import "chrome/browser/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/cocoa/toolbar_compressable.h"
#include "chrome/browser/cocoa/test_event_utils.h"
#import "chrome/browser/cocoa/view_resizer_pong.h"
#include "chrome/common/pref_names.h"
@@ -79,34 +78,6 @@
@end
-// A BookmarkBarController that always beleives that it's on the new tab page.
-@interface AlwaysNewTabPageBookmarkBarController : BookmarkBarControllerNoOpen {
-}
-@end
-
-@implementation AlwaysNewTabPageBookmarkBarController
--(BOOL)isNewTabPage {
- return YES;
-}
-@end
-
-@interface CompressablePong : NSObject<ToolbarCompressable> {
-@private
- BOOL compressed_;
-}
-@property (readonly) BOOL compressed;
-@end
-
-@implementation CompressablePong
-
-@synthesize compressed = compressed_;
-
-- (void)setShouldBeCompressed:(BOOL)compressed {
- compressed_ = compressed;
-}
-
-@end
-
namespace {
static const int kContentAreaHeight = 500;
@@ -116,7 +87,6 @@ class BookmarkBarControllerTest : public PlatformTest {
public:
BookmarkBarControllerTest() {
resizeDelegate_.reset([[ViewResizerPong alloc] init]);
- compressDelegate_.reset([[CompressablePong alloc] init]);
NSRect parent_frame = NSMakeRect(0, 0, 800, 50);
parent_view_.reset([[NSView alloc] initWithFrame:parent_frame]);
[parent_view_ setHidden:YES];
@@ -124,7 +94,7 @@ class BookmarkBarControllerTest : public PlatformTest {
[[BookmarkBarControllerNoOpen alloc]
initWithBrowser:helper_.browser()
initialWidth:NSWidth(parent_frame)
- compressDelegate:compressDelegate_.get()
+ delegate:nil
resizeDelegate:resizeDelegate_.get()]);
InstallAndToggleBar(bar_.get());
@@ -149,8 +119,17 @@ class BookmarkBarControllerTest : public PlatformTest {
frame.origin.y = 100;
[[[bar view] superview] setFrame:frame];
- // make sure it's open so certain things aren't no-ops
- helper_.profile()->GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, true);
+ // Make sure it's open so certain things aren't no-ops.
+ [bar updateAndShowNormalBar:YES
+ showDetachedBar:NO
+ withAnimation:NO];
+ }
+
+ // Update the state of the bookmark bar.
+ void UpdateBookmarkBar() {
+ [bar_ updateAndShowNormalBar:[bar_ isShownAsToolbar]
+ showDetachedBar:[bar_ isShownAsDetachedBar]
+ withAnimation:NO];
}
// Return a menu item that points to the right URL.
@@ -166,12 +145,10 @@ class BookmarkBarControllerTest : public PlatformTest {
return menu_item_;
}
-
CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc...
scoped_nsobject<NSView> parent_view_;
BrowserTestHelper helper_;
scoped_nsobject<ViewResizerPong> resizeDelegate_;
- scoped_nsobject<CompressablePong> compressDelegate_;
scoped_nsobject<BookmarkBarControllerNoOpen> bar_;
scoped_nsobject<NSMenu> menu_;
scoped_nsobject<NSMenuItem> menu_item_;
@@ -180,9 +157,11 @@ class BookmarkBarControllerTest : public PlatformTest {
};
TEST_F(BookmarkBarControllerTest, ShowWhenShowBookmarkBarTrue) {
- helper_.profile()->GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, true);
- [bar_ updateVisibility];
-
+ [bar_ updateAndShowNormalBar:YES
+ showDetachedBar:NO
+ withAnimation:NO];
+ EXPECT_TRUE([bar_ isShownAsToolbar]);
+ EXPECT_FALSE([bar_ isShownAsDetachedBar]);
EXPECT_TRUE([bar_ isVisible]);
EXPECT_FALSE([[bar_ view] isHidden]);
EXPECT_GT([resizeDelegate_ height], 0);
@@ -190,9 +169,11 @@ TEST_F(BookmarkBarControllerTest, ShowWhenShowBookmarkBarTrue) {
}
TEST_F(BookmarkBarControllerTest, HideWhenShowBookmarkBarFalse) {
- helper_.profile()->GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, false);
- [bar_ updateVisibility];
-
+ [bar_ updateAndShowNormalBar:NO
+ showDetachedBar:NO
+ withAnimation:NO];
+ EXPECT_FALSE([bar_ isShownAsToolbar]);
+ EXPECT_FALSE([bar_ isShownAsDetachedBar]);
EXPECT_FALSE([bar_ isVisible]);
EXPECT_TRUE([[bar_ view] isHidden]);
EXPECT_EQ(0, [resizeDelegate_ height]);
@@ -200,10 +181,12 @@ TEST_F(BookmarkBarControllerTest, HideWhenShowBookmarkBarFalse) {
}
TEST_F(BookmarkBarControllerTest, HideWhenShowBookmarkBarTrueButDisabled) {
- helper_.profile()->GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, true);
[bar_ setBookmarkBarEnabled:NO];
- [bar_ updateVisibility];
-
+ [bar_ updateAndShowNormalBar:YES
+ showDetachedBar:NO
+ withAnimation:NO];
+ EXPECT_TRUE([bar_ isShownAsToolbar]);
+ EXPECT_FALSE([bar_ isShownAsDetachedBar]);
EXPECT_FALSE([bar_ isVisible]);
EXPECT_TRUE([[bar_ view] isHidden]);
EXPECT_EQ(0, [resizeDelegate_ height]);
@@ -211,24 +194,15 @@ TEST_F(BookmarkBarControllerTest, HideWhenShowBookmarkBarTrueButDisabled) {
}
TEST_F(BookmarkBarControllerTest, ShowOnNewTabPage) {
- helper_.profile()->GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, false);
-
- scoped_nsobject<BookmarkBarControllerTogglePong> bar;
- bar.reset(
- [[AlwaysNewTabPageBookmarkBarController alloc]
- initWithBrowser:helper_.browser()
- initialWidth:800 // arbitrary
- compressDelegate:compressDelegate_.get()
- resizeDelegate:resizeDelegate_.get()]);
- InstallAndToggleBar(bar.get());
-
- [bar setBookmarkBarEnabled:NO];
- [bar updateVisibility];
-
- EXPECT_TRUE([bar isVisible]);
- EXPECT_FALSE([[bar view] isHidden]);
- EXPECT_GT([resizeDelegate_ height], 0);
- EXPECT_GT([[bar view] frame].size.height, 0);
+ [bar_ updateAndShowNormalBar:NO
+ showDetachedBar:YES
+ withAnimation:NO];
+ EXPECT_FALSE([bar_ isShownAsToolbar]);
+ EXPECT_TRUE([bar_ isShownAsDetachedBar]);
+ EXPECT_TRUE([bar_ isVisible]);
+ EXPECT_FALSE([[bar_ view] isHidden]);
+ ;EXPECT_GT([resizeDelegate_ height], 0);
+ EXPECT_GT([[bar_ view] frame].size.height, 0);
// Make sure no buttons fall off the bar, either now or when resized
// bigger or smaller.
@@ -237,23 +211,29 @@ TEST_F(BookmarkBarControllerTest, ShowOnNewTabPage) {
for (unsigned x = 0; x < arraysize(sizes); x++) {
// Confirm the buttons moved from the last check (which may be
// init but that's fine).
- CGFloat newX = [[bar offTheSideButton] frame].origin.x;
+ CGFloat newX = [[bar_ offTheSideButton] frame].origin.x;
EXPECT_NE(previousX, newX);
previousX = newX;
- // Confirm the buttons have a reasonable bounds.
- EXPECT_TRUE(NSContainsRect([[bar buttonView] frame],
- [[bar offTheSideButton] frame]));
- EXPECT_TRUE(NSContainsRect([[bar buttonView] frame],
- [[bar otherBookmarksButton] frame]));
+ // Confirm the buttons have a reasonable bounds. Recall that |-frame|
+ // returns rectangles in the superview's coordinates.
+ NSRect buttonViewFrame =
+ [[bar_ buttonView] convertRect:[[bar_ buttonView] frame]
+ fromView:[[bar_ buttonView] superview]];
+ EXPECT_EQ([bar_ buttonView], [[bar_ offTheSideButton] superview]);
+ EXPECT_TRUE(NSContainsRect(buttonViewFrame,
+ [[bar_ offTheSideButton] frame]));
+ EXPECT_EQ([bar_ buttonView], [[bar_ otherBookmarksButton] superview]);
+ EXPECT_TRUE(NSContainsRect(buttonViewFrame,
+ [[bar_ otherBookmarksButton] frame]));
// Now move them implicitly.
// We confirm FrameChangeNotification works in the next unit test;
// we simply assume it works here to resize or reposition the
// buttons above.
- NSRect frame = [[bar view] frame];
+ NSRect frame = [[bar_ view] frame];
frame.size.width += sizes[x];
- [[bar view] setFrame:frame];
+ [[bar_ view] setFrame:frame];
}
}
@@ -264,7 +244,7 @@ TEST_F(BookmarkBarControllerTest, FrameChangeNotification) {
[[BookmarkBarControllerTogglePong alloc]
initWithBrowser:helper_.browser()
initialWidth:100 // arbitrary
- compressDelegate:compressDelegate_.get()
+ delegate:nil
resizeDelegate:resizeDelegate_.get()]);
InstallAndToggleBar(bar.get());
@@ -415,13 +395,17 @@ TEST_F(BookmarkBarControllerTest, TestAddRemoveAndClear) {
EXPECT_EQ(initial_subview_count, [[buttonView subviews] count]);
GURL gurl1("http://superfriends.hall-of-justice.edu");
- std::wstring title1(L"Protectors of the Universe");
+ // Short titles increase the chances of this test succeeding if the view is
+ // narrow.
+ // TODO(viettrungluu): make the test independent of window/view size, font
+ // metrics, button size and spacing, and everything else.
+ std::wstring title1(L"x");
model->SetURLStarred(gurl1, title1, true);
EXPECT_EQ(1U, [[bar_ buttons] count]);
EXPECT_EQ(1+initial_subview_count, [[buttonView subviews] count]);
GURL gurl2("http://legion-of-doom.gov");
- std::wstring title2(L"Bad doodz");
+ std::wstring title2(L"y");
model->SetURLStarred(gurl2, title2, true);
EXPECT_EQ(2U, [[bar_ buttons] count]);
EXPECT_EQ(2+initial_subview_count, [[buttonView subviews] count]);
diff --git a/chrome/browser/cocoa/bookmark_bar_toolbar_view.h b/chrome/browser/cocoa/bookmark_bar_toolbar_view.h
index 0eb79ca..2232309 100644
--- a/chrome/browser/cocoa/bookmark_bar_toolbar_view.h
+++ b/chrome/browser/cocoa/bookmark_bar_toolbar_view.h
@@ -12,9 +12,8 @@
#import <Cocoa/Cocoa.h>
-#import "chrome/browser/cocoa/background_gradient_view.h"
+#import "chrome/browser/cocoa/animatable_view.h"
-@protocol BookmarkBarFloating;
@class BookmarkBarView;
class TabContents;
class ThemeProvider;
@@ -22,8 +21,8 @@ class ThemeProvider;
// An interface to allow mocking of a BookmarkBarController by the
// BookmarkBarToolbarView.
@protocol BookmarkBarToolbarViewController
-// Displaying the bookmark toolbar background in floating mode requires the
-// size of the currently selected tab to properly calculate where the
+// Displaying the bookmark toolbar background in bubble (floating) mode requires
+// the size of the currently selected tab to properly calculate where the
// background image is joined.
- (int)currentTabContentsHeight;
@@ -32,11 +31,11 @@ class ThemeProvider;
// Returns true if the bookmark bar should be drawn as if it's a disconnected
// bookmark bar on the New Tag Page.
-- (BOOL)drawAsFloatingBar;
+- (BOOL)isShownAsDetachedBar;
@end
-@interface BookmarkBarToolbarView : BackgroundGradientView {
+@interface BookmarkBarToolbarView : AnimatableView {
@private
// The controller which tells us how we should be drawing (as normal or as a
// floating bar).
diff --git a/chrome/browser/cocoa/bookmark_bar_toolbar_view.mm b/chrome/browser/cocoa/bookmark_bar_toolbar_view.mm
index 119192e..1a9b7ce 100644
--- a/chrome/browser/cocoa/bookmark_bar_toolbar_view.mm
+++ b/chrome/browser/cocoa/bookmark_bar_toolbar_view.mm
@@ -17,18 +17,18 @@
const CGFloat kBorderRadius = 3.0;
@interface BookmarkBarToolbarView (Private)
-- (void)drawRectAsFloating:(NSRect)rect;
+- (void)drawRectAsBubble:(NSRect)rect;
@end
@implementation BookmarkBarToolbarView
- (BOOL)isOpaque {
- return [controller_ drawAsFloatingBar];
+ return [controller_ isShownAsDetachedBar];
}
- (void)drawRect:(NSRect)rect {
- if ([controller_ drawAsFloatingBar]) {
- [self drawRectAsFloating:rect];
+ if ([controller_ isShownAsDetachedBar]) {
+ [self drawRectAsBubble:rect];
} else {
NSPoint phase = [self gtm_themePatternPhase];
[[NSGraphicsContext currentContext] setPatternPhase:phase];
@@ -36,7 +36,7 @@ const CGFloat kBorderRadius = 3.0;
}
}
-- (void)drawRectAsFloating:(NSRect)rect {
+- (void)drawRectAsBubble:(NSRect)rect {
NSRect bounds = [self bounds];
ThemeProvider* themeProvider = [controller_ themeProvider];
diff --git a/chrome/browser/cocoa/bookmark_bar_toolbar_view_unittest.mm b/chrome/browser/cocoa/bookmark_bar_toolbar_view_unittest.mm
index a6414f4..5073764 100644
--- a/chrome/browser/cocoa/bookmark_bar_toolbar_view_unittest.mm
+++ b/chrome/browser/cocoa/bookmark_bar_toolbar_view_unittest.mm
@@ -22,8 +22,7 @@ using ::testing::DoAll;
using ::testing::Return;
using ::testing::SetArgumentPointee;
-// When testing the floating drawing, we need to have a source of
-// theme data.
+// When testing the floating drawing, we need to have a source of theme data.
class MockThemeProvider : public ThemeProvider {
public:
// Cross platform methods
@@ -53,27 +52,27 @@ class MockThemeProvider : public ThemeProvider {
@end
// Allows us to control which way the view is rendered.
-@interface DrawFloatingFakeController :
+@interface DrawDetachedBarFakeController :
NSObject<BookmarkBarToolbarViewController> {
int current_tab_contents_height_;
ThemeProvider* theme_provider_;
- BOOL drawAsFloating_;
+ BOOL isShownAsDetachedBar_;
}
@property(assign) int currentTabContentsHeight;
@property(assign) ThemeProvider* themeProvider;
-@property(assign) BOOL drawAsFloatingBar;
+@property(assign) BOOL isShownAsDetachedBar;
@end
-@implementation DrawFloatingFakeController
+@implementation DrawDetachedBarFakeController
@synthesize currentTabContentsHeight = current_tab_contents_height_;
@synthesize themeProvider = theme_provider_;
-@synthesize drawAsFloatingBar = drawAsFloating_;
+@synthesize isShownAsDetachedBar = isShownAsDetachedBar_;
@end
class BookmarkBarToolbarViewTest : public PlatformTest {
public:
BookmarkBarToolbarViewTest() {
- controller_.reset([[DrawFloatingFakeController alloc] init]);
+ controller_.reset([[DrawDetachedBarFakeController alloc] init]);
NSRect frame = NSMakeRect(0, 0, 400, 40);
view_.reset([[BookmarkBarToolbarView alloc] initWithFrame:frame]);
[cocoa_helper_.contentView() addSubview:view_.get()];
@@ -81,7 +80,7 @@ class BookmarkBarToolbarViewTest : public PlatformTest {
}
CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc...
- scoped_nsobject<DrawFloatingFakeController> controller_;
+ scoped_nsobject<DrawDetachedBarFakeController> controller_;
scoped_nsobject<BookmarkBarToolbarView> view_;
};
@@ -95,13 +94,13 @@ TEST_F(BookmarkBarToolbarViewTest, AddRemove) {
// Test drawing (part 1), mostly to ensure nothing leaks or crashes.
TEST_F(BookmarkBarToolbarViewTest, DisplayAsNormalBar) {
- [controller_.get() setDrawAsFloatingBar:NO];
+ [controller_.get() setIsShownAsDetachedBar:NO];
[view_ display];
}
// Test drawing (part 2), mostly to ensure nothing leaks or crashes.
-TEST_F(BookmarkBarToolbarViewTest, DisplayAsFloatingBarWithNoImage) {
- [controller_.get() setDrawAsFloatingBar:YES];
+TEST_F(BookmarkBarToolbarViewTest, DisplayAsDetachedBarWithNoImage) {
+ [controller_.get() setIsShownAsDetachedBar:YES];
// Tests where we don't have a background image, only a color.
MockThemeProvider provider;
@@ -114,7 +113,7 @@ TEST_F(BookmarkBarToolbarViewTest, DisplayAsFloatingBarWithNoImage) {
[view_ display];
}
-// Actions used in DisplayAsFloatingBarWithBgImage.
+// Actions used in DisplayAsDetachedBarWithBgImage.
ACTION(SetBackgroundTiling) {
*arg1 = BrowserThemeProvider::NO_REPEAT;
return true;
@@ -126,8 +125,8 @@ ACTION(SetAlignLeft) {
}
// Test drawing (part 3), mostly to ensure nothing leaks or crashes.
-TEST_F(BookmarkBarToolbarViewTest, DisplayAsFloatingBarWithBgImage) {
- [controller_.get() setDrawAsFloatingBar:YES];
+TEST_F(BookmarkBarToolbarViewTest, DisplayAsDetachedBarWithBgImage) {
+ [controller_.get() setIsShownAsDetachedBar:YES];
// Tests where we have a background image, with positioning information.
MockThemeProvider provider;
diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm
index 8e5b50b..f38dd2d 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/cocoa/browser_window_cocoa.mm
@@ -423,7 +423,7 @@ void BrowserWindowCocoa::Observe(NotificationType type,
// Only the key window gets a direct toggle from the menu.
// Other windows hear about it from the notification.
case NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED:
- [controller_ updateBookmarkBarVisibility];
+ [controller_ updateBookmarkBarVisibilityWithAnimation:YES];
break;
default:
NOTREACHED(); // we don't ask for anything else!
diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h
index 7156778..d7fedde 100644
--- a/chrome/browser/cocoa/browser_window_controller.h
+++ b/chrome/browser/cocoa/browser_window_controller.h
@@ -44,6 +44,7 @@ class TabStripModelObserverBridge;
@interface BrowserWindowController :
TabWindowController<NSUserInterfaceValidations,
+ BookmarkBarControllerDelegate,
BookmarkBubbleControllerDelegate,
BrowserCommandExecutor,
ViewResizer,
@@ -122,8 +123,9 @@ class TabStripModelObserverBridge;
- (BOOL)isBookmarkBarVisible;
-// Called after the visibility perf changed.
-- (void)updateBookmarkBarVisibility;
+// Called after bookmark bar visibility changes (due to pref change or change in
+// tab/tab contents).
+- (void)updateBookmarkBarVisibilityWithAnimation:(BOOL)animate;
- (BOOL)isDownloadShelfVisible;
diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm
index 65d0475..1eb90c8 100644
--- a/chrome/browser/cocoa/browser_window_controller.mm
+++ b/chrome/browser/cocoa/browser_window_controller.mm
@@ -42,6 +42,7 @@
#import "chrome/browser/cocoa/toolbar_controller.h"
#import "chrome/browser/browser_theme_provider.h"
#include "chrome/browser/sync/sync_status_ui_helper.h"
+#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#import "chrome/browser/cocoa/background_gradient_view.h"
#include "grit/generated_resources.h"
@@ -84,6 +85,13 @@ willPositionSheet:(NSWindow*)sheet
// Repositions the windows subviews.
- (void)layoutSubviews;
+// Should we show the normal bookmark bar?
+- (BOOL)shouldShowBookmarkBar;
+
+// Is the current page one for which the bookmark should be shown detached *if*
+// the normal bookmark bar is not shown?
+- (BOOL)shouldShowDetachedBookmarkBar;
+
@end
@@ -176,7 +184,7 @@ willPositionSheet:(NSWindow*)sheet
[[BookmarkBarController alloc]
initWithBrowser:browser_.get()
initialWidth:NSWidth([[[self window] contentView] frame])
- compressDelegate:toolbarController_.get()
+ delegate:self
resizeDelegate:self]);
// Add bookmark bar to the view hierarchy. This also triggers the
@@ -192,10 +200,10 @@ willPositionSheet:(NSWindow*)sheet
[bookmarkBarController_ setBookmarkBarEnabled:NO];
}
- // We don't want to try and show the bar before it gets placed in
- // it's parent view, so this step shoudn't be inside the bookmark
- // bar controller's awakeFromNib.
- [bookmarkBarController_ showIfNeeded];
+ // We don't want to try and show the bar before it gets placed in its parent
+ // view, so this step shoudn't be inside the bookmark bar controller's
+ // |-awakeFromNib|.
+ [self updateBookmarkBarVisibilityWithAnimation:NO];
if (browser_->SupportsWindowFeature(Browser::FEATURE_EXTENSIONSHELF)) {
// Create the extension shelf.
@@ -474,10 +482,10 @@ willPositionSheet:(NSWindow*)sheet
view == [downloadShelfController_ view] ||
view == [bookmarkBarController_ view]);
- // Change the height of the view and call layoutViews. We set the height here
- // without regard to where the view is on the screen or whether it needs to
- // "grow up" or "grow down." The below call to layoutSubviews will position
- // each view correctly.
+ // Change the height of the view and call |-layoutSubViews|. We set the height
+ // here without regard to where the view is on the screen or whether it needs
+ // to "grow up" or "grow down." The below call to |-layoutSubviews| will
+ // position each view correctly.
NSRect frame = [view frame];
if (frame.size.height == height)
return;
@@ -934,8 +942,11 @@ willPositionSheet:(NSWindow*)sheet
return [bookmarkBarController_ isVisible];
}
-- (void)updateBookmarkBarVisibility {
- [bookmarkBarController_ updateVisibility];
+- (void)updateBookmarkBarVisibilityWithAnimation:(BOOL)animate {
+ [bookmarkBarController_
+ updateAndShowNormalBar:[self shouldShowBookmarkBar]
+ showDetachedBar:[self shouldShowDetachedBookmarkBar]
+ withAnimation:animate];
}
- (BOOL)isDownloadShelfVisible {
@@ -1082,6 +1093,9 @@ willPositionSheet:(NSWindow*)sheet
UpdateToolbar(newContents, true);
UpdateUIForContents(newContents);
#endif
+
+ // Update the bookmark bar.
+ [self updateBookmarkBarVisibilityWithAnimation:NO];
}
- (void)tabChangedWithContents:(TabContents*)contents
@@ -1091,6 +1105,9 @@ willPositionSheet:(NSWindow*)sheet
// Update titles if this is the currently selected tab.
windowShim_->UpdateTitleBar();
}
+
+ // Update the bookmark bar.
+ [self updateBookmarkBarVisibilityWithAnimation:NO];
}
- (void)userChangedTheme {
@@ -1199,6 +1216,28 @@ willPositionSheet:(NSWindow*)sheet
}
}
+// (Needed for |BookmarkBarControllerDelegate| protocol.)
+- (void)bookmarkBar:(BookmarkBarController*)controller
+ didChangeFromState:(bookmarks::VisualState)oldState
+ toState:(bookmarks::VisualState)newState {
+ [toolbarController_
+ setHeightCompression:[controller getDesiredToolbarHeightCompression]];
+ [toolbarController_ setShowsDivider:[controller shouldToolbarShowDivider]];
+
+ // TODO(viettrungluu): anything else?
+}
+
+// (Needed for |BookmarkBarControllerDelegate| protocol.)
+- (void)bookmarkBar:(BookmarkBarController*)controller
+willAnimateFromState:(bookmarks::VisualState)oldState
+ toState:(bookmarks::VisualState)newState {
+ [toolbarController_
+ setHeightCompression:[controller getDesiredToolbarHeightCompression]];
+ [toolbarController_ setShowsDivider:[controller shouldToolbarShowDivider]];
+
+ // TODO(viettrungluu): anything else?
+}
+
@end
@implementation BrowserWindowController (Private)
@@ -1285,25 +1324,30 @@ willPositionSheet:(NSWindow*)sheet
- (NSRect)window:(NSWindow*)window
willPositionSheet:(NSWindow*)sheet
usingRect:(NSRect)defaultSheetRect {
- // Any sheet should come from right above the apparent content area, or
- // equivalently right below the apparent toolbar.
- NSRect toolbarFrame = [[toolbarController_ view] frame];
- defaultSheetRect.origin.y = toolbarFrame.origin.y;
-
- // Position as follows:
- // - On a normal (non-NTP) page, position the sheet under the bookmark bar if
- // it's visible. Else put it immediately below the normal toolbar.
- // - On the NTP, if the bookmark bar is enabled ("always visible"), then it
- // looks like a normal bookmark bar, so position the sheet under it; if it
- // isn't enabled, the bookmark bar will look as if it's a part of the
- // content area, so just put it immediately below the toolbar.
- if ([bookmarkBarController_ isVisible] &&
- (![bookmarkBarController_ isNewTabPage] ||
- [bookmarkBarController_ isAlwaysVisible])) {
- NSRect bookmarkBarFrame = [[bookmarkBarController_ view] frame];
- defaultSheetRect.origin.y -= bookmarkBarFrame.size.height;
+ // Position the sheet as follows:
+ // - If the bookmark bar is hidden or shown as a bubble (on the NTP when the
+ // bookmark bar is disabled), position the sheet immediately below the
+ // normal toolbar.
+ // - If the bookmark bar is shown (attached to the normal toolbar), position
+ // the sheet below the bookmark bar.
+ // - If the bookmark bar is currently animating, position the sheet according
+ // to where the bar will be when the animation ends.
+ switch ([bookmarkBarController_ visualState]) {
+ case bookmarks::kShowingState: {
+ NSRect bookmarkBarFrame = [[bookmarkBarController_ view] frame];
+ defaultSheetRect.origin.y = bookmarkBarFrame.origin.y;
+ break;
+ }
+ case bookmarks::kHiddenState:
+ case bookmarks::kDetachedState: {
+ NSRect toolbarFrame = [[toolbarController_ view] frame];
+ defaultSheetRect.origin.y = toolbarFrame.origin.y;
+ break;
+ }
+ default:
+ case bookmarks::kInvalidState:
+ NOTREACHED();
}
-
return defaultSheetRect;
}
@@ -1384,7 +1428,18 @@ willPositionSheet:(NSWindow*)sheet
}
[toolbarView setFrame:toolbarFrame];
- if ([bookmarkBarController_ isAlwaysVisible]) {
+ bookmarks::VisualState bookmarkBarState =
+ [bookmarkBarController_ visualState];
+ bookmarks::VisualState lastBookmarkBarState =
+ [bookmarkBarController_ lastVisualState];
+
+ // If the bookmark bar is showing, or animating between showing and hidden,
+ // place the bookmark bar immediately below the toolbar.
+ // TODO(viettrungluu): Improve/abstract this when I implement other
+ // animations.
+ if ((bookmarkBarState == bookmarks::kShowingState) ||
+ (bookmarkBarState == bookmarks::kHiddenState &&
+ lastBookmarkBarState == bookmarks::kShowingState)) {
NSView* bookmarkBarView = [bookmarkBarController_ view];
[bookmarkBarView setHidden:NO];
NSRect bookmarkBarFrame = [bookmarkBarView frame];
@@ -1402,8 +1457,8 @@ willPositionSheet:(NSWindow*)sheet
[infoBarView setFrame:infoBarFrame];
maxY -= NSHeight(infoBarFrame);
- if (![bookmarkBarController_ isAlwaysVisible] &&
- [bookmarkBarController_ isVisible]) {
+ // If the bookmark bar is detached, place it at the bottom of the stack.
+ if (bookmarkBarState == bookmarks::kDetachedState) {
NSView* bookmarkBarView = [bookmarkBarController_ view];
[bookmarkBarView setHidden:NO];
NSRect bookmarkBarFrame = [bookmarkBarView frame];
@@ -1413,12 +1468,6 @@ willPositionSheet:(NSWindow*)sheet
maxY -= NSHeight(bookmarkBarFrame);
}
- if (![bookmarkBarController_ isVisible]) {
- // If the bookmark bar is not visible in either mode, we need to hide it
- // otherwise it'll render over other elements.
- [[bookmarkBarController_ view] setHidden:YES];
- }
-
// Place the extension shelf at the bottom of the view, if it exists.
if (extensionShelfController_.get()) {
NSView* extensionView = [extensionShelfController_ view];
@@ -1453,15 +1502,22 @@ willPositionSheet:(NSWindow*)sheet
verticalOffsetForStatusBubble_ = minY;
- // The bottom of the visible toolbar stack is the one that shows the
- // divider stroke. If the bookmark bar is visible and not in new tab page
- // mode, it is the bottom visible toolbar and so it must, otherwise the
- // main toolbar is.
- BOOL bookmarkToolbarShowsDivider = [bookmarkBarController_ isAlwaysVisible];
- [[toolbarController_ backgroundGradientView]
- setShowsDivider:!bookmarkToolbarShowsDivider];
- [[bookmarkBarController_ backgroundGradientView]
- setShowsDivider:bookmarkToolbarShowsDivider];
+ // Normally, we don't need to tell the toolbar whether or not to show the
+ // divider, but things break down during animation.
+ [toolbarController_
+ setShowsDivider:[bookmarkBarController_ shouldToolbarShowDivider]];
+}
+
+- (BOOL)shouldShowBookmarkBar {
+ DCHECK(browser_.get());
+ return browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar) ?
+ YES : NO;
+}
+
+- (BOOL)shouldShowDetachedBookmarkBar {
+ DCHECK(browser_.get());
+ TabContents* contents = browser_->GetSelectedTabContents();
+ return (contents && contents->ShouldShowBookmarkBar()) ? YES : NO;
}
@end
diff --git a/chrome/browser/cocoa/browser_window_controller_unittest.mm b/chrome/browser/cocoa/browser_window_controller_unittest.mm
index e2b7451..b03d095 100644
--- a/chrome/browser/cocoa/browser_window_controller_unittest.mm
+++ b/chrome/browser/cocoa/browser_window_controller_unittest.mm
@@ -105,6 +105,7 @@ TEST_F(BrowserWindowControllerTest, TestNormal) {
// Force the bookmark bar to be shown.
browser_helper_.profile()->GetPrefs()->
SetBoolean(prefs::kShowBookmarkBar, true);
+ [controller_ updateBookmarkBarVisibilityWithAnimation:NO];
// Make sure a normal BrowserWindowController is, uh, normal.
EXPECT_TRUE([controller_ isNormalWindow]);
@@ -139,7 +140,7 @@ TEST_F(BrowserWindowControllerTest, BookmarkBarControllerIndirection) {
browser_helper_.profile()->GetPrefs()->
SetBoolean(prefs::kShowBookmarkBar, true);
- [controller_ updateBookmarkBarVisibility];
+ [controller_ updateBookmarkBarVisibilityWithAnimation:NO];
EXPECT_TRUE([controller_ isBookmarkBarVisible]);
}
diff --git a/chrome/browser/cocoa/toolbar_compressable.h b/chrome/browser/cocoa/toolbar_compressable.h
deleted file mode 100644
index ddd21c4..0000000
--- a/chrome/browser/cocoa/toolbar_compressable.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_COCOA_TOOLBAR_COMPRESSABLE_H_
-#define CHROME_BROWSER_COCOA_TOOLBAR_COMPRESSABLE_H_
-
-#include "chrome/browser/tabs/tab_strip_model.h"
-
-#import <Cocoa/Cocoa.h>
-
-// Defines a protocol that allows one view to tell another view that it should
-// remove pixels from the bottom of the view. Only ToolbarController implements
-// this, but it's a protocol for unit testing reasons.
-@protocol ToolbarCompressable
-- (void)setShouldBeCompressed:(BOOL)compressed;
-@end
-
-#endif // CHROME_BROWSER_COCOA_TOOLBAR_COMPRESSABLE_H_
diff --git a/chrome/browser/cocoa/toolbar_controller.h b/chrome/browser/cocoa/toolbar_controller.h
index 991ff39..f46e264 100644
--- a/chrome/browser/cocoa/toolbar_controller.h
+++ b/chrome/browser/cocoa/toolbar_controller.h
@@ -10,7 +10,6 @@
#include "base/scoped_ptr.h"
#include "base/scoped_nsobject.h"
#import "chrome/browser/cocoa/command_observer_bridge.h"
-#import "chrome/browser/cocoa/toolbar_compressable.h"
#import "chrome/browser/cocoa/delayedmenu_button.h"
#import "chrome/browser/cocoa/view_resizer.h"
#include "chrome/common/pref_member.h"
@@ -18,7 +17,6 @@
@class AutocompleteTextField;
@class AutocompleteTextFieldEditor;
@class BackForwardMenuController;
-@class BackgroundGradientView;
class Browser;
@class BrowserActionsController;
class BubblePositioner;
@@ -41,7 +39,7 @@ class ToolbarView;
// the web content view.
@interface ToolbarController :
- NSViewController<CommandObserverProtocol, ToolbarCompressable> {
+ NSViewController<CommandObserverProtocol> {
@private
ToolbarModel* toolbarModel_; // weak, one per window
CommandUpdater* commands_; // weak, one per window
@@ -111,9 +109,6 @@ class ToolbarView;
// returns nil if we don't want to override the custom field editor for |obj|.
- (id)customFieldEditorForObject:(id)obj;
-// Returns the backdrop to the toolbar.
-- (BackgroundGradientView*)backgroundGradientView;
-
// Make the location bar the first responder, if possible.
- (void)focusLocationBar;
@@ -140,6 +135,14 @@ class ToolbarView;
// Somewhere near the star button seems like a good start.
- (NSRect)starButtonInWindowCoordinates;
+// Chop off the bottom of the toolbar by |compressByHeight|; needed when the
+// bookmark bar is attached.
+- (void)setHeightCompression:(CGFloat)compressByHeight;
+
+// Display (or not) the divider (line at bottom); needed when the bookmark bar
+// is attached.
+- (void)setShowsDivider:(BOOL)showDivider;
+
@end
// A set of private methods used by tests, in the absence of "friends" in ObjC.
diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm
index 9092b51..8653f49 100644
--- a/chrome/browser/cocoa/toolbar_controller.mm
+++ b/chrome/browser/cocoa/toolbar_controller.mm
@@ -15,6 +15,7 @@
#import "chrome/browser/cocoa/autocomplete_text_field.h"
#import "chrome/browser/cocoa/autocomplete_text_field_editor.h"
#import "chrome/browser/cocoa/back_forward_menu_controller.h"
+#import "chrome/browser/cocoa/background_gradient_view.h"
#import "chrome/browser/cocoa/encoding_menu_controller_delegate_mac.h"
#import "chrome/browser/cocoa/extensions/browser_actions_controller.h"
#import "chrome/browser/cocoa/gradient_button_cell.h"
@@ -45,12 +46,10 @@ static NSString* const kWrenchButtonImageName = @"menu_chrome_Template.pdf";
// Height of the toolbar in pixels when the bookmark bar is closed.
static const float kBaseToolbarHeight = 36.0;
-// Overlap (in pixels) between the toolbar and the bookmark bar.
-static const float kBookmarkBarOverlap = 6.0;
-
@interface ToolbarController(Private)
- (void)initCommandStatus:(CommandUpdater*)commands;
- (void)prefChanged:(std::wstring*)prefName;
+- (BackgroundGradientView*)backgroundGradientView;
- (void)browserActionsChanged;
- (void)adjustLocationAndGoPositionsBy:(CGFloat)dX;
@end
@@ -352,7 +351,10 @@ class PrefObserverBridge : public NotificationObserver {
return locationBar_;
}
+// (Private) Returns the backdrop to the toolbar.
- (BackgroundGradientView*)backgroundGradientView {
+ // We really do mean |[super view]|; see our override of |-view|.
+ DCHECK([[super view] isKindOfClass:[BackgroundGradientView class]]);
return (BackgroundGradientView*)[super view];
}
@@ -514,14 +516,16 @@ class PrefObserverBridge : public NotificationObserver {
fromView:starButton_];
}
-- (void)setShouldBeCompressed:(BOOL)compressed {
- CGFloat newToolbarHeight = kBaseToolbarHeight;
- if (compressed)
- newToolbarHeight -= kBookmarkBarOverlap;
-
+- (void)setHeightCompression:(CGFloat)compressByHeight {
+ // Resize.
+ CGFloat newToolbarHeight = kBaseToolbarHeight - compressByHeight;
[resizeDelegate_ resizeView:[self view] newHeight:newToolbarHeight];
}
+- (void)setShowsDivider:(BOOL)showDivider {
+ [[self backgroundGradientView] setShowsDivider:showDivider];
+}
+
- (NSString*)view:(NSView*)view
stringForToolTip:(NSToolTipTag)tag
point:(NSPoint)point
diff --git a/chrome/browser/cocoa/toolbar_controller_unittest.mm b/chrome/browser/cocoa/toolbar_controller_unittest.mm
index 5c731fd..37b20cb 100644
--- a/chrome/browser/cocoa/toolbar_controller_unittest.mm
+++ b/chrome/browser/cocoa/toolbar_controller_unittest.mm
@@ -296,14 +296,11 @@ TEST_F(ToolbarControllerTest, PopulateEncodingMenu) {
EXPECT_NE(0, [encodings numberOfItems]);
}
-TEST_F(ToolbarControllerTest, CorrectHeightWhenCompressed) {
- [bar_ setShouldBeCompressed:YES];
- EXPECT_EQ(30.0, [resizeDelegate_ height]);
-}
-
-TEST_F(ToolbarControllerTest, CorrectHeightWhenUnompressed) {
- [bar_ setShouldBeCompressed:NO];
- EXPECT_EQ(36.0, [resizeDelegate_ height]);
+TEST_F(ToolbarControllerTest, HeightCompression) {
+ for (int i = 0; i <= 10; i++) {
+ [bar_ setHeightCompression:static_cast<CGFloat>(i)];
+ EXPECT_EQ(static_cast<CGFloat>(36 - i), [resizeDelegate_ height]);
+ }
}
} // namespace
diff --git a/chrome/browser/cocoa/view_resizer_pong.mm b/chrome/browser/cocoa/view_resizer_pong.mm
index 9246af7..78879e9 100644
--- a/chrome/browser/cocoa/view_resizer_pong.mm
+++ b/chrome/browser/cocoa/view_resizer_pong.mm
@@ -14,6 +14,7 @@
[self setHeight:height];
// Set the view's height and width, in case it uses that as important state.
- [view setFrame:NSMakeRect(100, 100, 250, height)];
+ [view setFrame:NSMakeRect(100, 50,
+ NSWidth([[view superview] frame]) - 50, height)];
}
@end