summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/nibs/InfoBarContainer.xib34
-rw-r--r--chrome/browser/cocoa/bookmark_bar_bridge_unittest.mm24
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller.h35
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller.mm127
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller_unittest.mm51
-rw-r--r--chrome/browser/cocoa/browser_window_controller.h6
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm236
-rw-r--r--chrome/browser/cocoa/browser_window_controller_unittest.mm133
-rw-r--r--chrome/browser/cocoa/download_shelf_controller.h15
-rw-r--r--chrome/browser/cocoa/download_shelf_controller.mm59
-rw-r--r--chrome/browser/cocoa/download_shelf_mac.mm1
-rw-r--r--chrome/browser/cocoa/download_shelf_mac_unittest.mm8
-rw-r--r--chrome/browser/cocoa/find_bar_cocoa_controller.h5
-rw-r--r--chrome/browser/cocoa/find_bar_cocoa_controller.mm22
-rw-r--r--chrome/browser/cocoa/infobar_container_controller.h8
-rw-r--r--chrome/browser/cocoa/infobar_container_controller.mm9
-rw-r--r--chrome/browser/cocoa/infobar_container_controller_unittest.mm37
-rw-r--r--chrome/browser/cocoa/toolbar_controller.h10
-rw-r--r--chrome/browser/cocoa/toolbar_controller.mm35
-rw-r--r--chrome/browser/cocoa/toolbar_controller_unittest.mm34
-rw-r--r--chrome/browser/cocoa/view_resizer.h21
-rw-r--r--chrome/browser/cocoa/view_resizer_pong.h21
-rw-r--r--chrome/browser/cocoa/view_resizer_pong.mm19
-rw-r--r--chrome/chrome.gyp3
24 files changed, 512 insertions, 441 deletions
diff --git a/chrome/app/nibs/InfoBarContainer.xib b/chrome/app/nibs/InfoBarContainer.xib
index b7e5d8c..3ff7934 100644
--- a/chrome/app/nibs/InfoBarContainer.xib
+++ b/chrome/app/nibs/InfoBarContainer.xib
@@ -8,6 +8,7 @@
<string key="IBDocument.HIToolboxVersion">353.00</string>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="1"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -34,9 +35,10 @@
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSCustomView" id="1005">
- <nil key="NSNextResponder"/>
+ <reference key="NSNextResponder"/>
<int key="NSvFlags">266</int>
- <string key="NSFrameSize">{480, 30}</string>
+ <string key="NSFrameSize">{480, 0}</string>
+ <reference key="NSSuperview"/>
<string key="NSClassName">NSView</string>
</object>
</object>
@@ -108,7 +110,7 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{379, 587}, {480, 30}}</string>
+ <string>{{379, 617}, {480, 0}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{628, 654}</string>
<string>{{357, 416}, {480, 272}}</string>
@@ -140,27 +142,35 @@
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
+ <string key="className">InfoBarContainerController</string>
+ <string key="superclassName">NSViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">resizeDelegate_</string>
+ <string key="NS.object.0">id</string>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/infobar_container_controller.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
- <string key="minorKey">browser/cocoa/tab_strip_model_observer_bridge.h</string>
+ <string key="minorKey">browser/cocoa/status_bubble_mac.h</string>
</object>
</object>
- </object>
- <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.1+">
- <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
- <string key="className">InfoBarContainerController</string>
- <string key="superclassName">NSViewController</string>
+ <string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBDocumentRelativeSource</string>
- <string key="minorKey">../../../browser/cocoa/infobar_container_controller.h</string>
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/cocoa/tab_strip_model_observer_bridge.h</string>
</object>
</object>
</object>
</object>
<int key="IBDocument.localizationMode">0</int>
- <string key="IBDocument.LastKnownRelativeProjectPath">../../../chrome.xcodeproj</string>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../../chrome.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
</data>
</archive>
diff --git a/chrome/browser/cocoa/bookmark_bar_bridge_unittest.mm b/chrome/browser/cocoa/bookmark_bar_bridge_unittest.mm
index 158069b..f260903 100644
--- a/chrome/browser/cocoa/bookmark_bar_bridge_unittest.mm
+++ b/chrome/browser/cocoa/bookmark_bar_bridge_unittest.mm
@@ -32,15 +32,11 @@ typedef std::pair<GURL,WindowOpenDisposition> OpenInfo;
@implementation FakeBookmarkBarController
-- (id)initWithProfile:(Profile*)profile
- parentView:(NSView*)parentView
- webContentView:(NSView*)webContentView
- infoBarsView:(NSView*)infoBarsView {
+- (id)initWithProfile:(Profile*)profile {
if ((self = [super initWithProfile:profile
- parentView:parentView
- webContentView:webContentView
- infoBarsView:infoBarsView
- delegate:self])) {
+ initialWidth:100 // arbitrary
+ resizeDelegate:nil
+ urlDelegate:self])) {
callbacks_.reset([[NSMutableArray alloc] init]);
}
return self;
@@ -96,14 +92,8 @@ typedef std::pair<GURL,WindowOpenDisposition> OpenInfo;
class BookmarkBarBridgeTest : public testing::Test {
public:
- BookmarkBarBridgeTest() {
- NSRect content_frame = NSMakeRect(0, 0, 100, 100);
- view_.reset([[NSView alloc] initWithFrame:content_frame]);
- }
-
CocoaTestHelper cocoa_helper_;
BrowserTestHelper browser_test_helper_;
- scoped_nsobject<NSView> view_;
};
// Call all the callbacks; make sure they are all redirected to the objc object.
@@ -119,11 +109,7 @@ TEST_F(BookmarkBarBridgeTest, TestRedirect) {
[[NSView alloc] initWithFrame:NSMakeRect(0,0,100,100)]);
scoped_nsobject<FakeBookmarkBarController>
- controller([[FakeBookmarkBarController alloc]
- initWithProfile:profile
- parentView:parentView.get()
- webContentView:webView.get()
- infoBarsView:infoBarsView.get()]);
+ controller([[FakeBookmarkBarController alloc] initWithProfile:profile]);
EXPECT_TRUE(controller.get());
scoped_ptr<BookmarkBarBridge> bridge(new BookmarkBarBridge(controller.get(),
model));
diff --git a/chrome/browser/cocoa/bookmark_bar_controller.h b/chrome/browser/cocoa/bookmark_bar_controller.h
index c035fc2..23b211c 100644
--- a/chrome/browser/cocoa/bookmark_bar_controller.h
+++ b/chrome/browser/cocoa/bookmark_bar_controller.h
@@ -20,6 +20,7 @@ class BookmarkNode;
class GURL;
class Profile;
class PrefService;
+@protocol ViewResizer;
// The interface for an object which can open URLs for a bookmark.
@protocol BookmarkURLOpener
@@ -36,12 +37,8 @@ class PrefService;
BookmarkModel* bookmarkModel_; // weak; part of the profile owned by the
// top-level Browser object.
- // Currently these two are always the same when not in fullscreen
- // mode, but they mean slightly different things.
- // contentAreaHasOffset_ is an implementation detail of bookmark bar
- // show state.
- BOOL contentViewHasOffset_;
- BOOL barShouldBeShown_;
+ // Our initial view width, which is applied in awakeFromNib.
+ float initialWidth_;
// BookmarkNodes have a 64bit id. NSMenuItems have a 32bit tag used
// to represent the bookmark node they refer to. This map provides
@@ -57,16 +54,18 @@ class PrefService;
// Set when using fullscreen mode.
BOOL barIsEnabled_;
- NSView* parentView_; // weak; our parent view
- NSView* webContentView_; // weak; where the web goes
- NSView* infoBarsView_; // weak; where the infobars go
+ // Set to YES when the user elects to always show the bookmark bar.
+ BOOL barShouldBeShown_;
// Bridge from Chrome-style C++ notifications (e.g. derived from
// BookmarkModelObserver)
scoped_ptr<BookmarkBarBridge> bridge_;
- // Delegate which can open URLs for us.
- id<BookmarkURLOpener> delegate_; // weak
+ // Delegate that can resize us.
+ id<ViewResizer> resizeDelegate_; // weak
+
+ // Delegate that can open URLs for us.
+ id<BookmarkURLOpener> urlDelegate_; // weak
IBOutlet NSView* buttonView_;
IBOutlet NSButton* offTheSideButton_;
@@ -74,15 +73,11 @@ class PrefService;
}
// Initializes the bookmark bar controller with the given browser
-// profile, parent view (the toolbar), web content view, and delegate.
-// |delegate| is used for opening URLs.
-// TODO(rohitrao, jrg): The bookmark bar shouldn't know about the
-// infoBarsView or the webContentView.
+// profile and delegates.
- (id)initWithProfile:(Profile*)profile
- parentView:(NSView*)parentView
- webContentView:(NSView*)webContentView
- infoBarsView:(NSView*)infoBarsView
- delegate:(id<BookmarkURLOpener>)delegate;
+ initialWidth:(float)initialWidth
+ resizeDelegate:(id<ViewResizer>)resizeDelegate
+ urlDelegate:(id<BookmarkURLOpener>)urlDelegate;
// Returns whether or not the bookmark bar is visible.
- (BOOL)isBookmarkBarVisible;
@@ -138,7 +133,7 @@ class PrefService;
// These APIs should only be used by unit tests (or used internally).
@interface BookmarkBarController(InternalOrTestingAPI)
// Set the delegate for a unit test.
-- (void)setDelegate:(id<BookmarkURLOpener>)delegate;
+- (void)setUrlDelegate:(id<BookmarkURLOpener>)urlDelegate;
- (void)clearBookmarkBar;
- (NSView*)buttonView;
- (NSArray*)buttons;
diff --git a/chrome/browser/cocoa/bookmark_bar_controller.mm b/chrome/browser/cocoa/bookmark_bar_controller.mm
index d32ecbf..8fede00 100644
--- a/chrome/browser/cocoa/bookmark_bar_controller.mm
+++ b/chrome/browser/cocoa/bookmark_bar_controller.mm
@@ -14,6 +14,7 @@
#import "chrome/browser/cocoa/bookmark_editor_controller.h"
#import "chrome/browser/cocoa/bookmark_name_folder_controller.h"
#import "chrome/browser/cocoa/bookmark_menu_cocoa_controller.h"
+#import "chrome/browser/cocoa/view_resizer.h"
#include "chrome/browser/cocoa/nsimage_cache.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"
@@ -31,15 +32,8 @@
namespace {
-// TODO(jrg): this is the right proportional height but overlaps the
-// "blue outline" of the omnibox. Fix.
-
// Our height, when opened.
const int kBookmarkBarHeight = 30;
-// How much to adjust our parent view.
-const int kBookmarkBarSuperviewHeightAdjustment = 25;
-// How much to adjust the web frame.
-const int kBookmarkBarWebframeHeightAdjustment = 25;
// Magic numbers from Cole
const CGFloat kDefaultBookmarkWidth = 150.0;
@@ -50,19 +44,17 @@ const CGFloat kBookmarkHorizontalPadding = 1.0;
@implementation BookmarkBarController
- (id)initWithProfile:(Profile*)profile
- parentView:(NSView*)parentView
- webContentView:(NSView*)webContentView
- infoBarsView:(NSView*)infoBarsView
- delegate:(id<BookmarkURLOpener>)delegate {
+ initialWidth:(float)initialWidth
+ resizeDelegate:(id<ViewResizer>)resizeDelegate
+ urlDelegate:(id<BookmarkURLOpener>)urlDelegate {
if ((self = [super initWithNibName:@"BookmarkBar"
bundle:mac_util::MainAppBundle()])) {
profile_ = profile;
+ initialWidth_ = initialWidth;
bookmarkModel_ = profile->GetBookmarkModel();
- parentView_ = parentView;
- webContentView_ = webContentView;
- infoBarsView_ = infoBarsView;
buttons_.reset([[NSMutableArray alloc] init]);
- delegate_ = delegate;
+ resizeDelegate_ = resizeDelegate;
+ urlDelegate_ = urlDelegate;
}
return self;
}
@@ -75,14 +67,11 @@ const CGFloat kBookmarkHorizontalPadding = 1.0;
- (void)awakeFromNib {
// We default to NOT open, which means height=0.
DCHECK([[self view] isHidden]); // Hidden so it's OK to change.
- NSRect frame = [[self view] frame];
- frame.size.height = 0;
- frame.size.width = [parentView_ frame].size.width;
- [[self view] setFrame:frame];
-
- // Make sure the nodes stay bottom-aligned.
- [[self view] setAutoresizingMask:(NSViewWidthSizable |
- NSViewMinYMargin)];
+
+ // Set our initial height to zero, since that is what the superview
+ // expects. We will resize ourselves open later if needed.
+ [[self view] setFrame:NSMakeRect(0, 0, initialWidth_, 0)];
+
// Be sure to enable the bar before trying to show it...
barIsEnabled_ = YES;
if (profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar))
@@ -135,82 +124,16 @@ const CGFloat kBookmarkHorizontalPadding = 1.0;
// determine desired state.
- (void)showBookmarkBar:(BOOL)show immediately:(BOOL)immediately {
if (barIsEnabled_ && (barShouldBeShown_ != show)) {
- contentViewHasOffset_ = show;
- [[self view] setHidden:show ? NO : YES];
+ if ([self view]) {
+ [[self view] setHidden:show ? NO : YES];
+ [resizeDelegate_ resizeView:[self view]
+ newHeight:(show ? kBookmarkBarHeight : 0)];
+ }
barShouldBeShown_ = show;
if (show) {
[self loaded:bookmarkModel_];
}
- [self applyContentAreaOffset:show immediately:immediately];
- }
-}
-
-// Apply a contents box offset to make (or remove) room for the
-// bookmark bar. If apply==YES, always make room (the contentView_ is
-// "full size"). If apply==NO we are trying to undo an offset. If no
-// offset there is nothing to undo.
-//
-// TODO(jrg): it is awkward we change the sizes of views for our
-// parent and siblings; ideally they change their own sizes.
-//
-// TODO(jrg): unlike windows, we process events while an animator is
-// running. Thus, if you resize the window while the bookmark bar is
-// animating, you'll mess things up. Fix.
-- (void)applyContentAreaOffset:(BOOL)apply immediately:(BOOL)immediately {
- if ([self view] == nil) {
- // We're too early, but awakeFromNib will call me again.
- return;
- }
- if (!contentViewHasOffset_ && apply) {
- // There is no offset to unconditionally apply.
- return;
- }
-
- // None of these locals are members of the Hall of Justice.
- NSRect superframe = [parentView_ frame];
- NSRect frame = [[self view] frame];
- NSRect webframe = [webContentView_ frame];
- NSRect infoframe = [infoBarsView_ frame];
- if (apply) {
- superframe.size.height += kBookmarkBarSuperviewHeightAdjustment;
- // TODO(jrg): y=0 if we add the bookmark bar before the parent
- // view (toolbar) is placed in the view hierarchy. A different
- // CL, where the bookmark bar is extracted from the toolbar nib,
- // may fix this awkwardness.
- if (superframe.origin.y > 0) {
- superframe.origin.y -= kBookmarkBarSuperviewHeightAdjustment;
- webframe.size.height -= kBookmarkBarWebframeHeightAdjustment;
- }
- frame.size.height += kBookmarkBarHeight;
- infoframe.origin.y -= kBookmarkBarWebframeHeightAdjustment;
- } else {
- superframe.size.height -= kBookmarkBarSuperviewHeightAdjustment;
- superframe.origin.y += kBookmarkBarSuperviewHeightAdjustment;
- frame.size.height -= kBookmarkBarHeight;
- webframe.size.height += kBookmarkBarWebframeHeightAdjustment;
- infoframe.origin.y += kBookmarkBarWebframeHeightAdjustment;
}
-
- // TODO(jrg): Animators can be a little fussy. Setting these three
- // off can sometimes causes races where the finish isn't as
- // expected. Fix, or clean out the animators as an option.
- // Odd racing is FAR worse than a lack of an animator.
- if (1 /* immediately */) {
- [parentView_ setFrame:superframe];
- [webContentView_ setFrame:webframe];
- [infoBarsView_ setFrame:infoframe];
- [[self view] setFrame:frame];
- } else {
- [[parentView_ animator] setFrame:superframe];
- [[webContentView_ animator] setFrame:webframe];
- [[infoBarsView_ animator] setFrame:infoframe];
- [[[self view] animator] setFrame:frame];
- }
-
- [[self view] setNeedsDisplay:YES];
- [parentView_ setNeedsDisplay:YES];
- [webContentView_ setNeedsDisplay:YES];
- [infoBarsView_ setNeedsDisplay:YES];
}
- (BOOL)isBookmarkBarVisible {
@@ -259,7 +182,7 @@ const CGFloat kBookmarkHorizontalPadding = 1.0;
- (IBAction)openBookmark:(id)sender {
BookmarkNode* node = [self nodeFromButton:sender];
- [delegate_ openBookmarkURL:node->GetURL() disposition:CURRENT_TAB];
+ [urlDelegate_ openBookmarkURL:node->GetURL() disposition:CURRENT_TAB];
}
// Given a NSMenuItem tag, return the appropriate bookmark node id.
@@ -382,17 +305,17 @@ const CGFloat kBookmarkHorizontalPadding = 1.0;
- (IBAction)openBookmarkInNewForegroundTab:(id)sender {
BookmarkNode* node = [self nodeFromMenuItem:sender];
- [delegate_ openBookmarkURL:node->GetURL() disposition:NEW_FOREGROUND_TAB];
+ [urlDelegate_ openBookmarkURL:node->GetURL() disposition:NEW_FOREGROUND_TAB];
}
- (IBAction)openBookmarkInNewWindow:(id)sender {
BookmarkNode* node = [self nodeFromMenuItem:sender];
- [delegate_ openBookmarkURL:node->GetURL() disposition:NEW_WINDOW];
+ [urlDelegate_ openBookmarkURL:node->GetURL() disposition:NEW_WINDOW];
}
- (IBAction)openBookmarkInIncognitoWindow:(id)sender {
BookmarkNode* node = [self nodeFromMenuItem:sender];
- [delegate_ openBookmarkURL:node->GetURL() disposition:OFF_THE_RECORD];
+ [urlDelegate_ openBookmarkURL:node->GetURL() disposition:OFF_THE_RECORD];
}
- (IBAction)editBookmark:(id)sender {
@@ -431,7 +354,7 @@ const CGFloat kBookmarkHorizontalPadding = 1.0;
for (int i = 0; i < node->GetChildCount(); i++) {
BookmarkNode* child = node->GetChild(i);
if (child->is_url())
- [delegate_ openBookmarkURL:child->GetURL()
+ [urlDelegate_ openBookmarkURL:child->GetURL()
disposition:NEW_BACKGROUND_TAB];
else
[self openBookmarkNodesRecursive:child];
@@ -572,7 +495,7 @@ const CGFloat kBookmarkHorizontalPadding = 1.0;
- (IBAction)openBookmarkMenuItem:(id)sender {
int64 tag = [self nodeIdFromMenuTag:[sender tag]];
const BookmarkNode* node = bookmarkModel_->GetNodeByID(tag);
- [delegate_ openBookmarkURL:node->GetURL() disposition:CURRENT_TAB];
+ [urlDelegate_ openBookmarkURL:node->GetURL() disposition:CURRENT_TAB];
}
// Add all items from the given model to our bookmark bar.
@@ -700,8 +623,8 @@ const CGFloat kBookmarkHorizontalPadding = 1.0;
[self loaded:model];
}
-- (void)setDelegate:(id<BookmarkURLOpener>)delegate {
- delegate_ = delegate;
+- (void)setUrlDelegate:(id<BookmarkURLOpener>)urlDelegate {
+ urlDelegate_ = urlDelegate;
}
- (NSArray*)buttons {
diff --git a/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm b/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm
index 2f4b9f6..161f12a 100644
--- a/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm
+++ b/chrome/browser/cocoa/bookmark_bar_controller_unittest.mm
@@ -9,6 +9,7 @@
#import "chrome/browser/cocoa/bookmark_bar_controller.h"
#include "chrome/browser/cocoa/browser_test_helper.h"
#import "chrome/browser/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/cocoa/view_resizer_pong.h"
#include "testing/gtest/include/gtest/gtest.h"
// Pretend BookmarkURLOpener delegate to keep track of requests
@@ -81,21 +82,15 @@ static const int kInfoBarViewHeight = 30;
class BookmarkBarControllerTest : public testing::Test {
public:
BookmarkBarControllerTest() {
- NSRect content_frame = NSMakeRect(0, 0, 800, kContentAreaHeight);
- // |infobar_frame| is set to be directly above |content_frame|.
- NSRect infobar_frame = NSMakeRect(0, kContentAreaHeight,
- 800, kInfoBarViewHeight);
+ resizeDelegate_.reset([[ViewResizerPong alloc] init]);
NSRect parent_frame = NSMakeRect(0, 0, 800, 50);
- content_area_.reset([[NSView alloc] initWithFrame:content_frame]);
- infobar_view_.reset([[NSView alloc] initWithFrame:infobar_frame]);
parent_view_.reset([[NSView alloc] initWithFrame:parent_frame]);
[parent_view_ setHidden:YES];
bar_.reset(
[[BookmarkBarController alloc] initWithProfile:helper_.profile()
- parentView:parent_view_.get()
- webContentView:content_area_.get()
- infoBarsView:infobar_view_.get()
- delegate:nil]);
+ initialWidth:NSWidth(parent_frame)
+ resizeDelegate:resizeDelegate_.get()
+ urlDelegate:nil]);
InstallAndToggleBar(bar_.get());
@@ -139,10 +134,9 @@ class BookmarkBarControllerTest : public testing::Test {
CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc...
- scoped_nsobject<NSView> content_area_;
- scoped_nsobject<NSView> infobar_view_;
scoped_nsobject<NSView> parent_view_;
BrowserTestHelper helper_;
+ scoped_nsobject<ViewResizerPong> resizeDelegate_;
scoped_nsobject<BookmarkBarController> bar_;
scoped_nsobject<NSMenu> menu_;
scoped_nsobject<NSMenuItem> menu_item_;
@@ -164,22 +158,14 @@ TEST_F(BookmarkBarControllerTest, ShowHide) {
[bar_ toggleBookmarkBar];
EXPECT_TRUE([bar_ isBookmarkBarVisible]);
EXPECT_FALSE([[bar_ view] isHidden]);
- NSRect content_frame = [content_area_ frame];
- NSRect infobar_frame = [infobar_view_ frame];
- EXPECT_NE(content_frame.size.height, kContentAreaHeight);
- EXPECT_EQ(NSMaxY(content_frame), NSMinY(infobar_frame));
- EXPECT_EQ(kInfoBarViewHeight, infobar_frame.size.height);
+ EXPECT_GT([resizeDelegate_ height], 0);
EXPECT_GT([[bar_ view] frame].size.height, 0);
[bar_ toggleBookmarkBar];
EXPECT_FALSE([bar_ isBookmarkBarVisible]);
EXPECT_TRUE([[bar_ view] isHidden]);
- content_frame = [content_area_ frame];
- infobar_frame = [infobar_view_ frame];
- EXPECT_EQ(content_frame.size.height, kContentAreaHeight);
- EXPECT_EQ(NSMaxY(content_frame), NSMinY(infobar_frame));
- EXPECT_EQ(kInfoBarViewHeight, infobar_frame.size.height);
- EXPECT_EQ([[bar_ view] frame].size.height, 0);
+ EXPECT_EQ(0, [resizeDelegate_ height]);
+ EXPECT_EQ(0, [[bar_ view] frame].size.height);
}
// Make sure we're watching for frame change notifications.
@@ -188,10 +174,9 @@ TEST_F(BookmarkBarControllerTest, FrameChangeNotification) {
bar.reset(
[[BookmarkBarControllerTogglePong alloc]
initWithProfile:helper_.profile()
- parentView:parent_view_.get()
- webContentView:content_area_.get()
- infoBarsView:infobar_view_.get()
- delegate:nil]);
+ initialWidth:100 // arbitrary
+ resizeDelegate:resizeDelegate_.get()
+ urlDelegate:nil]);
InstallAndToggleBar(bar.get());
EXPECT_GT([bar toggles], 0);
@@ -294,7 +279,7 @@ TEST_F(BookmarkBarControllerTest, OpenBookmark) {
scoped_ptr<BookmarkNode> node(new BookmarkNode(gurl));
scoped_nsobject<BookmarkURLOpenerPong> pong([[BookmarkURLOpenerPong alloc]
init]);
- [bar_ setDelegate:pong.get()];
+ [bar_ setUrlDelegate:pong.get()];
scoped_nsobject<NSButtonCell> cell([[NSButtonCell alloc] init]);
scoped_nsobject<NSButton> button([[NSButton alloc] init]);
@@ -305,7 +290,7 @@ TEST_F(BookmarkBarControllerTest, OpenBookmark) {
EXPECT_EQ(pong.get()->urls_[0], node->GetURL());
EXPECT_EQ(pong.get()->dispositions_[0], CURRENT_TAB);
- [bar_ setDelegate:nil];
+ [bar_ setUrlDelegate:nil];
}
// Confirm opening of bookmarks works from the menus (different
@@ -313,7 +298,7 @@ TEST_F(BookmarkBarControllerTest, OpenBookmark) {
TEST_F(BookmarkBarControllerTest, OpenBookmarkFromMenus) {
scoped_nsobject<BookmarkURLOpenerPong> pong([[BookmarkURLOpenerPong alloc]
init]);
- [bar_ setDelegate:pong.get()];
+ [bar_ setUrlDelegate:pong.get()];
const char* urls[] = { "http://walla.walla.ding.dong.com",
"http://i_dont_know.com",
@@ -334,7 +319,7 @@ TEST_F(BookmarkBarControllerTest, OpenBookmarkFromMenus) {
EXPECT_EQ(pong.get()->dispositions_[0], dispositions[i]);
[pong clear];
}
- [bar_ setDelegate:nil];
+ [bar_ setUrlDelegate:nil];
}
TEST_F(BookmarkBarControllerTest, TestAddRemoveAndClear) {
@@ -458,7 +443,7 @@ TEST_F(BookmarkBarControllerTest, DeleteBookmark) {
TEST_F(BookmarkBarControllerTest, OpenAllBookmarks) {
scoped_nsobject<BookmarkURLOpenerPong> pong([[BookmarkURLOpenerPong alloc]
init]);
- [bar_ setDelegate:pong.get()];
+ [bar_ setUrlDelegate:pong.get()];
BookmarkModel* model = helper_.profile()->GetBookmarkModel();
const BookmarkNode* parent = model->GetBookmarkBarNode();
@@ -493,7 +478,7 @@ TEST_F(BookmarkBarControllerTest, OpenAllBookmarks) {
EXPECT_EQ(pong.get()->dispositions_[3], NEW_BACKGROUND_TAB);
- [bar_ setDelegate:nil];
+ [bar_ setUrlDelegate:nil];
}
// TODO(jrg): write a test to confirm that nodeFavIconLoaded calls
diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h
index 382acf2..5ebbbf0 100644
--- a/chrome/browser/cocoa/browser_window_controller.h
+++ b/chrome/browser/cocoa/browser_window_controller.h
@@ -16,6 +16,7 @@
#include "base/scoped_ptr.h"
#import "chrome/browser/cocoa/tab_window_controller.h"
#import "chrome/browser/cocoa/bookmark_bar_controller.h"
+#import "chrome/browser/cocoa/view_resizer.h"
#import "third_party/GTM/AppKit/GTMTheme.h"
class Browser;
@@ -37,6 +38,7 @@ class TabStripModelObserverBridge;
@interface BrowserWindowController :
TabWindowController<NSUserInterfaceValidations,
BookmarkURLOpener,
+ ViewResizer,
GTMThemeDelegate> {
@private
// The ordering of these members is important as it determines the order in
@@ -124,10 +126,6 @@ class TabStripModelObserverBridge;
// Returns fullscreen state.
- (BOOL)isFullscreen;
-// Sent when the infobar view has been resized and other content needs
-// to be shifted around it.
-- (void)infoBarResized:(float)newHeight;
-
// The user changed the theme.
- (void)userChangedTheme;
diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm
index a6c3012..bb073ec 100644
--- a/chrome/browser/cocoa/browser_window_controller.mm
+++ b/chrome/browser/cocoa/browser_window_controller.mm
@@ -66,20 +66,12 @@ const int kWindowGradientHeight = 24;
@interface BrowserWindowController(Private)
-- (void)positionInfoBar;
-- (void)positionBar; // toolbar or URL bar
-- (void)removeBar; // toolbar or URL bar
-
// Leopard's gradient heuristic gets confused by our tabs and makes the title
// gradient jump when creating a tab that is less than a tab width from the
// right side of the screen. This function disables Leopard's gradient
// heuristic.
- (void)fixWindowGradient;
-// Called by the Notification Center whenever the tabContentArea's
-// frame changes. Re-positions the bookmark bar and the find bar.
-- (void)tabContentAreaFrameChanged:(id)sender;
-
// Saves the window's position in the local state preferences.
- (void)saveWindowPositionIfNeeded;
@@ -97,6 +89,9 @@ willPositionSheet:(NSWindow*)sheet
// Theme up the window.
- (void)applyTheme;
+
+// Repositions the windows subviews.
+- (void)layoutSubviews;
@end
@@ -165,12 +160,12 @@ willPositionSheet:(NSWindow*)sheet
model:browser_->tabstrip_model()]);
// Create the infobar container view, so we can pass it to the
- // ToolbarController, but do not position the view until after the
- // toolbar is in place, as positionToolbar will move the tab content area.
+ // ToolbarController.
infoBarContainerController_.reset(
[[InfoBarContainerController alloc]
initWithTabStripModel:(browser_->tabstrip_model())
- browserWindowController:self]);
+ resizeDelegate:self]);
+ [[[self window] contentView] addSubview:[infoBarContainerController_ view]];
// Create a controller for the toolbar, giving it the toolbar model object
// and the toolbar view from the nib. The controller will handle
@@ -179,30 +174,19 @@ willPositionSheet:(NSWindow*)sheet
initWithModel:browser->toolbar_model()
commands:browser->command_updater()
profile:browser->profile()
- webContentView:[self tabContentArea]
- infoBarsView:[infoBarContainerController_ view]
+ resizeDelegate:self
bookmarkDelegate:self]);
// If we are a pop-up, we have a titlebar and no toolbar.
if (!browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) &&
browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR)) {
[toolbarController_ setHasToolbar:NO];
}
- [self positionBar];
- [self fixWindowGradient];
+ [[[self window] contentView] addSubview:[toolbarController_ view]];
- // Put the infobar container view into the window above the
- // tabcontentarea. There are no infobars when starting up, so its
- // initial height is 0.
- [self positionInfoBar];
+ [self fixWindowGradient];
- // Register ourselves for frame changed notifications from the
- // tabContentArea. This has to come after all of the resizing and
- // positioning above.
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(tabContentAreaFrameChanged:)
- name:nil
- object:[self tabContentArea]];
+ // Force a relayout of all the various bars.
+ [self layoutSubviews];
// Create the bridge for the status bubble.
statusBubble_.reset(new StatusBubbleMac([self window], self));
@@ -236,7 +220,6 @@ willPositionSheet:(NSWindow*)sheet
// window destruction.
[window_ setDelegate:nil];
- [[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
@@ -338,8 +321,6 @@ willPositionSheet:(NSWindow*)sheet
}
}
-
-
// Called when the user clicks the zoom button (or selects it from the Window
// menu). Zoom to the appropriate size based on the content. Make sure we
// enforce a minimum width to ensure websites with small intrinsic widths
@@ -372,6 +353,32 @@ willPositionSheet:(NSWindow*)sheet
return frame;
}
+// Main method to resize browser window subviews. This method should be called
+// when resizing any child of the content view, rather than resizing the views
+// directly. If the view is already the correct height, does not force a
+// relayout.
+- (void)resizeView:(NSView*)view newHeight:(float)height {
+ // We should only ever be called for one of the following three views.
+ // |downloadShelfController_| may be nil.
+ DCHECK(view);
+ DCHECK(view == [toolbarController_ view] ||
+ view == [infoBarContainerController_ view] ||
+ view == [downloadShelfController_ 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.
+ NSRect frame = [view frame];
+ if (frame.size.height == height)
+ return;
+
+ frame.size.height = height;
+ // TODO(rohitrao): Determine if calling setFrame: twice is bad.
+ [view setFrame:frame];
+ [self layoutSubviews];
+}
+
// Update a toggle state for an NSMenuItem if modified.
// Take care to insure |item| looks like a NSMenuItem.
// Called by validateUserInterfaceItem:.
@@ -708,7 +715,9 @@ willPositionSheet:(NSWindow*)sheet
- (DownloadShelfController*)downloadShelf {
if (!downloadShelfController_.get()) {
downloadShelfController_.reset([[DownloadShelfController alloc]
- initWithBrowser:browser_.get() contentArea:[self tabContentArea]]);
+ initWithBrowser:browser_.get() resizeDelegate:self]);
+ [[[self window] contentView] addSubview:[downloadShelfController_ view]];
+ [downloadShelfController_ show:nil];
}
return downloadShelfController_;
}
@@ -719,8 +728,11 @@ willPositionSheet:(NSWindow*)sheet
// Create a controller for the findbar.
findBarCocoaController_.reset([findBarCocoaController retain]);
- [[[self window] contentView] addSubview:[findBarCocoaController_ view]];
- [findBarCocoaController_ positionFindBarView:[self tabContentArea]];
+ [[[self window] contentView] addSubview:[findBarCocoaController_ view]
+ positioned:NSWindowAbove
+ relativeTo:[toolbarController_ view]];
+ [findBarCocoaController_
+ positionFindBarView:[infoBarContainerController_ view]];
}
// Adjust the UI for fullscreen mode. E.g. when going fullscreen,
@@ -729,18 +741,23 @@ willPositionSheet:(NSWindow*)sheet
if (fullscreen) {
// Disable showing of the bookmark bar. This does not toggle the
// preference.
+ // TODO(jrg): Is this still necessary?
[[toolbarController_ bookmarkBarController] setBookmarkBarEnabled:NO];
// Make room for more content area.
- [self removeBar];
+ [[toolbarController_ view] removeFromSuperview];
// Hide the menubar, and allow it to un-hide when moving the mouse
// to the top of the screen. Does this eliminate the need for an
// info bubble describing how to exit fullscreen mode?
SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
} else {
SetSystemUIMode(kUIModeNormal, 0);
- [self positionBar];
+ [[[self window] contentView] addSubview:[toolbarController_ view]];
+ // TODO(jrg): Is this still necessary?
[[toolbarController_ bookmarkBarController] setBookmarkBarEnabled:YES];
}
+
+ // Force a relayout.
+ [self layoutSubviews];
}
- (NSWindow*)fullscreenWindow {
@@ -751,24 +768,27 @@ willPositionSheet:(NSWindow*)sheet
- (void)setFullscreen:(BOOL)fullscreen {
fullscreen_ = fullscreen;
if (fullscreen) {
- // Minimize our UI
- [self adjustUIForFullscreen:fullscreen];
// Move content to a new fullscreen window
NSView* content = [[self window] contentView];
fullscreen_window_.reset([[self fullscreenWindow] retain]);
[content removeFromSuperview];
[fullscreen_window_ setContentView:content];
[self setWindow:fullscreen_window_.get()];
+ // Minimize our UI. This call triggers a relayout, so it needs to come
+ // after we move the contentview to the new window.
+ [self adjustUIForFullscreen:fullscreen];
// Show one window, hide the other.
[fullscreen_window_ makeKeyAndOrderFront:self];
[content setNeedsDisplay:YES];
[window_ orderOut:self];
} else {
- [self adjustUIForFullscreen:fullscreen];
NSView* content = [fullscreen_window_ contentView];
[content removeFromSuperview];
[window_ setContentView:content];
[self setWindow:window_.get()];
+ // This call triggers a relayout, so it needs to come after we move the
+ // contentview to the new window.
+ [self adjustUIForFullscreen:fullscreen];
[content setNeedsDisplay:YES];
// With this call, valgrind yells at me about "Conditional jump or
@@ -851,22 +871,6 @@ willPositionSheet:(NSWindow*)sheet
[tabStripController_ userChangedTheme];
}
-// TODO(rohitrao, jrg): Move this logic out of BrowserWindowController?
-- (void)infoBarResized:(float)newHeight {
- // The top edge of the infobar is fixed.
- NSView* infoBarView = [infoBarContainerController_ view];
- NSRect infoBarFrame = [infoBarView frame];
- int maxY = NSMaxY(infoBarFrame);
- int minY = maxY - newHeight;
-
- [infoBarView setFrame:NSMakeRect(infoBarFrame.origin.x, minY,
- infoBarFrame.size.width, newHeight)];
-
- NSRect contentFrame = [[self tabContentArea] frame];
- contentFrame.size.height = minY - contentFrame.origin.y;
- [[self tabContentArea] setFrame:contentFrame];
-}
-
- (GTMTheme *)gtm_themeForWindow:(NSWindow*)window {
return theme_ ? theme_ : [GTMTheme defaultTheme];
}
@@ -875,60 +879,6 @@ willPositionSheet:(NSWindow*)sheet
@implementation BrowserWindowController (Private)
-// TODO(rohitrao, jrg): Move this logic out of BrowserWindowController?
-- (void)positionInfoBar {
- NSView* infoBarView = [infoBarContainerController_ view];
- NSRect infoBarFrame = [[self tabContentArea] frame];
- infoBarFrame.origin.y = NSMaxY(infoBarFrame);
- infoBarFrame.size.height = 0;
- [infoBarView setFrame:infoBarFrame];
- [[[self window] contentView] addSubview:infoBarView];
-}
-
-// If |add| is YES:
-// Position |barView| below the tab strip, but not as a sibling. The
-// toolbar or titlebar is part of the window's contentView, mainly
-// because we want the opacity during drags to be the same as the web
-// content. This can be used for either the initial add or a
-// reposition.
-// If |add| is NO:
-// Remove the toolbar or titlebar from it's parent view (the window's
-// content view). Called when going fullscreen and we need to
-// minimize UI.
-- (void)positionOrRemoveBar:(BOOL)add {
- NSView* barView = [toolbarController_ view];
- NSRect barFrame = [barView frame];
- NSView* contentView = [self tabContentArea];
- NSRect contentFrame = [contentView frame];
-
- // Shrink or grow the content area by the height of the toolbar.
- if (add)
- contentFrame.size.height -= barFrame.size.height;
- else
- contentFrame.size.height += barFrame.size.height;
- [contentView setFrame:contentFrame];
-
- if (add) {
- // Move the toolbar above the content area, within the window's content view
- // (as opposed to the tab strip, which is a sibling).
- barFrame.origin.y = NSMaxY(contentFrame);
- barFrame.origin.x = 0;
- barFrame.size.width = contentFrame.size.width;
- [barView setFrame:barFrame];
- [[[self window] contentView] addSubview:barView];
- } else {
- [barView removeFromSuperview];
- }
-}
-
-- (void)positionBar {
- [self positionOrRemoveBar:YES];
-}
-
-- (void)removeBar {
- [self positionOrRemoveBar:NO];
-}
-
// If the browser is in incognito mode, install the image view to decorate
// the window at the upper right. Use the same base y coordinate as the
// tab strip.
@@ -980,14 +930,6 @@ willPositionSheet:(NSWindow*)sheet
}
}
-- (void)tabContentAreaFrameChanged:(id)sender {
- // TODO(rohitrao): This is triggered by window resizes also. Make
- // sure we aren't doing anything wasteful in those cases.
- [downloadShelfController_ resizeDownloadShelf];
-
- [findBarCocoaController_ positionFindBarView:[self tabContentArea]];
-}
-
- (void)saveWindowPositionIfNeeded {
if (browser_ != BrowserList::GetLastActive())
return;
@@ -1081,6 +1023,68 @@ willPositionSheet:(NSWindow*)sheet
[[self window] setBackgroundColor:color];
}
+// Private method to layout browser window subviews. Positions the toolbar and
+// the infobar above the tab content area. Positions the download shelf below
+// the tab content area. If the toolbar is not a child of the contentview, this
+// method will not leave room for it. If we are currently running in fullscreen
+// mode, or if the tabstrip is not a descendant of the window, this method fills
+// the entire content area. Otherwise, this method places the topmost view
+// directly beneath the tabstrip.
+- (void)layoutSubviews {
+ NSView* contentView = fullscreen_ ? [fullscreen_window_ contentView]
+ : [[self window] contentView];
+ NSRect contentFrame = [contentView frame];
+ int maxY = NSMaxY(contentFrame);
+ int minY = NSMinY(contentFrame);
+ if (!fullscreen_ && [self isNormalWindow]) {
+ maxY = NSMinY([[self tabStripView] frame]);
+ }
+ DCHECK_GE(maxY, minY);
+
+ // Place the toolbar at the top of the reserved area, but only if we're not in
+ // fullscreen mode.
+ NSView* toolbarView = [toolbarController_ view];
+ NSRect toolbarFrame = [toolbarView frame];
+ if (!fullscreen_) {
+ // The toolbar is present in the window, so we make room for it.
+ toolbarFrame.origin.x = 0;
+ toolbarFrame.origin.y = maxY - NSHeight(toolbarFrame);
+ toolbarFrame.size.width = NSWidth(contentFrame);
+ maxY -= NSHeight(toolbarFrame);
+ }
+ [toolbarView setFrame:toolbarFrame];
+
+ // Place the infobar container in place below the toolbar.
+ NSView* infoBarView = [infoBarContainerController_ view];
+ NSRect infoBarFrame = [infoBarView frame];
+ infoBarFrame.origin.y = maxY - NSHeight(infoBarFrame);
+ infoBarFrame.size.width = NSWidth(contentFrame);
+ [infoBarView setFrame:infoBarFrame];
+ maxY -= NSHeight(infoBarFrame);
+
+ // Place the download shelf at the bottom of the view, if it exists.
+ if (downloadShelfController_.get()) {
+ NSView* downloadView = [downloadShelfController_ view];
+ NSRect downloadFrame = [downloadView frame];
+ downloadFrame.origin.y = minY;
+ downloadFrame.size.width = NSWidth(contentFrame);
+ [downloadView setFrame:downloadFrame];
+ minY += NSHeight(downloadFrame);
+ }
+
+ // Finally, the tabContentArea takes up all of the remaining space.
+ NSView* tabContentView = [self tabContentArea];
+ NSRect tabContentFrame = [tabContentView frame];
+ tabContentFrame.origin.y = minY;
+ tabContentFrame.size.height = maxY - minY;
+ tabContentFrame.size.width = NSWidth(contentFrame);
+ [tabContentView setFrame:tabContentFrame];
+
+ // Position the find bar relative to the infobar container.
+ [findBarCocoaController_
+ positionFindBarView:[infoBarContainerController_ view]];
+}
+
@end
@implementation GTMTheme (BrowserThemeProviderInitialization)
diff --git a/chrome/browser/cocoa/browser_window_controller_unittest.mm b/chrome/browser/cocoa/browser_window_controller_unittest.mm
index f816a76..4b40a67 100644
--- a/chrome/browser/cocoa/browser_window_controller_unittest.mm
+++ b/chrome/browser/cocoa/browser_window_controller_unittest.mm
@@ -15,8 +15,26 @@
#include "chrome/test/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
-@interface BrowserWindowController (ExposedForTesting)
+@interface BrowserWindowController (JustForTesting)
+// Already defined in BWC.
- (void)saveWindowPositionToPrefs:(PrefService*)prefs;
+- (void)layoutSubviews;
+@end
+
+@interface BrowserWindowController (ExposedForTesting)
+// Implementations are below.
+- (NSView*)infoBarContainerView;
+- (NSView*)toolbarView;
+@end
+
+@implementation BrowserWindowController (ExposedForTesting)
+- (NSView*)infoBarContainerView {
+ return [infoBarContainerController_ view];
+}
+
+- (NSView*)toolbarView {
+ return [toolbarController_ view];
+}
@end
class BrowserWindowControllerTest : public testing::Test {
@@ -52,13 +70,29 @@ TEST_F(BrowserWindowControllerTest, TestSaveWindowPosition) {
}
@interface BrowserWindowControllerFakeFullscreen : BrowserWindowController {
+ @private
+ // We release the window ourselves, so we don't have to rely on the unittest
+ // doing it for us.
+ scoped_nsobject<NSWindow> fullscreenWindow_;
}
@end
@implementation BrowserWindowControllerFakeFullscreen
-// This isn't needed to pass the test, but does prevent an actual
-// fullscreen from happening.
+// Override fullscreenWindow to return a dummy window. This isn't needed to
+// pass the test, but because the dummy window is only 100x100, it prevents the
+// real fullscreen window from flashing up and taking over the whole screen..
+// We have to return an actual window because layoutSubviews: looks at the
+// window's frame.
- (NSWindow*)fullscreenWindow {
- return nil;
+ if (fullscreenWindow_.get())
+ return fullscreenWindow_.get();
+
+ fullscreenWindow_.reset(
+ [[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,400,400)
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO]);
+ [fullscreenWindow_ setReleasedWhenClosed:NO];
+ return fullscreenWindow_.get();
}
@end
@@ -132,4 +166,95 @@ TEST_F(BrowserWindowControllerTest, TestIncognitoWidthSpace) {
}
#endif
+@interface BrowserWindowControllerResizePong : BrowserWindowController {
+}
+@end
+
+@implementation BrowserWindowControllerResizePong
+@end
+
+// Test to make sure resizing and relaying-out subviews works correctly.
+TEST_F(BrowserWindowControllerTest, TestResizeViews) {
+ TabStripView* tabstrip = [controller_ tabStripView];
+ NSView* contentView = [[tabstrip window] contentView];
+ NSView* toolbar = [controller_ toolbarView];
+ NSView* infobar = [controller_ infoBarContainerView];
+ NSView* contentArea = [controller_ tabContentArea];
+
+ // We need to muck with the views a bit to put us in a consistent state before
+ // we start resizing. In particular, we need to move the tab strip to be
+ // immediately above the content area, since we layout views to be directly
+ // under the tab strip. We also explicitly set the contentView's frame to be
+ // 800x600.
+ [contentView setFrame:NSMakeRect(0, 0, 800, 600)];
+ NSRect tabstripFrame = [tabstrip frame];
+ tabstripFrame.origin.y = NSMaxY([contentView frame]);
+ [tabstrip setFrame:tabstripFrame];
+
+ // Make sure each view is as tall as we expect.
+ ASSERT_EQ(39, NSHeight([toolbar frame]));
+ ASSERT_EQ(0, NSHeight([infobar frame]));
+
+ // Force a layout and check each view's frame.
+ // contentView should be at 0,0 800x600
+ // contentArea should be at 0,0 800x561
+ // infobar should be at 0,561 800x0
+ // toolbar should be at 0,561 800x39
+ [controller_ layoutSubviews];
+ EXPECT_TRUE(NSEqualRects([contentView frame], NSMakeRect(0, 0, 800, 600)));
+ EXPECT_TRUE(NSEqualRects([contentArea frame], NSMakeRect(0, 0, 800, 561)));
+ EXPECT_TRUE(NSEqualRects([infobar frame], NSMakeRect(0, 561, 800, 0)));
+ EXPECT_TRUE(NSEqualRects([toolbar frame], NSMakeRect(0, 561, 800, 39)));
+
+ // Expand the infobar to 60px and recheck
+ // contentView should be at 0,0 800x600
+ // contentArea should be at 0,0 800x501
+ // infobar should be at 0,501 800x60
+ // toolbar should be at 0,561 800x39
+ [controller_ resizeView:infobar newHeight:60];
+ EXPECT_TRUE(NSEqualRects([contentView frame], NSMakeRect(0, 0, 800, 600)));
+ EXPECT_TRUE(NSEqualRects([contentArea frame], NSMakeRect(0, 0, 800, 501)));
+ EXPECT_TRUE(NSEqualRects([infobar frame], NSMakeRect(0, 501, 800, 60)));
+ EXPECT_TRUE(NSEqualRects([toolbar frame], NSMakeRect(0, 561, 800, 39)));
+
+ // Expand the toolbar to 64px and recheck
+ // contentView should be at 0,0 800x600
+ // contentArea should be at 0,0 800x476
+ // infobar should be at 0,476 800x60
+ // toolbar should be at 0,536 800x64
+ [controller_ resizeView:toolbar newHeight:64];
+ EXPECT_TRUE(NSEqualRects([contentView frame], NSMakeRect(0, 0, 800, 600)));
+ EXPECT_TRUE(NSEqualRects([contentArea frame], NSMakeRect(0, 0, 800, 476)));
+ EXPECT_TRUE(NSEqualRects([infobar frame], NSMakeRect(0, 476, 800, 60)));
+ EXPECT_TRUE(NSEqualRects([toolbar frame], NSMakeRect(0, 536, 800, 64)));
+
+ // Add a 30px download shelf and recheck
+ // contentView should be at 0,0 800x600
+ // download should be at 0,0 800x30
+ // contentArea should be at 0,30 800x446
+ // infobar should be at 0,476 800x60
+ // toolbar should be at 0,536 800x64
+ NSView* download = [[controller_ downloadShelf] view];
+ [controller_ resizeView:download newHeight:30];
+ EXPECT_TRUE(NSEqualRects([contentView frame], NSMakeRect(0, 0, 800, 600)));
+ EXPECT_TRUE(NSEqualRects([download frame], NSMakeRect(0, 0, 800, 30)));
+ EXPECT_TRUE(NSEqualRects([contentArea frame], NSMakeRect(0, 30, 800, 446)));
+ EXPECT_TRUE(NSEqualRects([infobar frame], NSMakeRect(0, 476, 800, 60)));
+ EXPECT_TRUE(NSEqualRects([toolbar frame], NSMakeRect(0, 536, 800, 64)));
+
+ // Shrink the infobar to 0px and toolbar to 39px and recheck
+ // contentView should be at 0,0 800x600
+ // download should be at 0,0 800x30
+ // contentArea should be at 0,30 800x531
+ // infobar should be at 0,561 800x0
+ // toolbar should be at 0,561 800x39
+ [controller_ resizeView:infobar newHeight:0];
+ [controller_ resizeView:toolbar newHeight:39];
+ EXPECT_TRUE(NSEqualRects([contentView frame], NSMakeRect(0, 0, 800, 600)));
+ EXPECT_TRUE(NSEqualRects([download frame], NSMakeRect(0, 0, 800, 30)));
+ EXPECT_TRUE(NSEqualRects([contentArea frame], NSMakeRect(0, 30, 800, 531)));
+ EXPECT_TRUE(NSEqualRects([infobar frame], NSMakeRect(0, 561, 800, 0)));
+ EXPECT_TRUE(NSEqualRects([toolbar frame], NSMakeRect(0, 561, 800, 39)));
+}
+
/* TODO(???): test other methods of BrowserWindowController */
diff --git a/chrome/browser/cocoa/download_shelf_controller.h b/chrome/browser/cocoa/download_shelf_controller.h
index c72538a..9ace0d3 100644
--- a/chrome/browser/cocoa/download_shelf_controller.h
+++ b/chrome/browser/cocoa/download_shelf_controller.h
@@ -6,6 +6,7 @@
#include "base/scoped_nsobject.h"
#include "base/scoped_ptr.h"
+#import "chrome/browser/cocoa/view_resizer.h"
class BaseDownloadItemModel;
class Browser;
@@ -38,14 +39,9 @@ class DownloadShelf;
IBOutlet NSImageView* image_;
- // Currently these two are always the same, but they mean slightly different
- // things. |contentAreaHasOffset_| is an implementation detail of the download
- // shelf visibility.
- BOOL contentAreaHasOffset_;
BOOL barIsVisible_;
scoped_ptr<DownloadShelf> bridge_;
- NSView* contentArea_; // the browser's content area
float shelfHeight_;
// The download items we have added to our shelf.
@@ -53,9 +49,13 @@ class DownloadShelf;
// The container that contains (and clamps) all the download items.
IBOutlet NSView* itemContainerView_;
+
+ // Delegate that handles resizing our view.
+ id<ViewResizer> resizeDelegate_;
};
-- (id)initWithBrowser:(Browser*)browser contentArea:(NSView*)content;
+- (id)initWithBrowser:(Browser*)browser
+ resizeDelegate:(id<ViewResizer>)resizeDelegate;
- (DownloadShelf*)bridge;
- (BOOL)isVisible;
@@ -67,9 +67,6 @@ class DownloadShelf;
- (void)addDownloadItem:(BaseDownloadItemModel*)model;
-// Resizes the download shelf based on the state of the content area.
-- (void)resizeDownloadShelf;
-
// Remove a download, possibly via clearing browser data.
- (void)remove:(DownloadItemController*)download;
diff --git a/chrome/browser/cocoa/download_shelf_controller.mm b/chrome/browser/cocoa/download_shelf_controller.mm
index 0cb170a..8a63da9 100644
--- a/chrome/browser/cocoa/download_shelf_controller.mm
+++ b/chrome/browser/cocoa/download_shelf_controller.mm
@@ -40,7 +40,6 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8;
@interface DownloadShelfController(Private)
- (void)applyContentAreaOffset:(BOOL)apply;
-- (void)positionBar;
- (void)showDownloadShelf:(BOOL)enable;
- (void)resizeDownloadLinkToFit;
@end
@@ -49,14 +48,15 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8;
@implementation DownloadShelfController
- (id)initWithBrowser:(Browser*)browser
- contentArea:(NSView*)content {
+ resizeDelegate:(id<ViewResizer>)resizeDelegate {
if ((self = [super initWithNibName:@"DownloadShelf"
bundle:mac_util::MainAppBundle()])) {
- contentArea_ = content;
+ resizeDelegate_ = resizeDelegate;
shelfHeight_ = [[self view] bounds].size.height;
- [self positionBar];
- [[[contentArea_ window] contentView] addSubview:[self view]];
+ // Reset the download shelf's frame to zero. It will be properly positioned
+ // and sized the first time we try to set its height.
+ [[self view] setFrame:NSZeroRect];
downloadItemControllers_.reset([[NSMutableArray alloc] init]);
@@ -136,26 +136,6 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8;
return YES;
}
-// Initializes the download shelf at the bottom edge of |contentArea_|.
-- (void)positionBar {
- // Set the bar's height to zero and position it at the bottom of the content
- // area, within the window's content view (as opposed to the tab strip, which
- // is a sibling). We'll enlarge it and slide the content area up when we need
- // to show this strip.
- NSRect contentFrame = [contentArea_ frame];
- NSRect barFrame = NSMakeRect(0, 0, contentFrame.size.width, shelfHeight_);
- [[self view] setFrame:barFrame];
-}
-
-// Called when the contentArea's frame changes. Enlarge the view to stay with
-// the bottom of the contentArea.
-- (void)resizeDownloadShelf {
- NSRect barFrame = [[self view] frame];
- barFrame.origin.y = 0;
- barFrame.size.height = NSMinY([contentArea_ frame]);
- [[self view] setFrame:barFrame];
-}
-
- (void)remove:(DownloadItemController*)download {
// Look for the download in our controller array and remove it. This will
// explicity release it so that it removes itself as an Observer of the
@@ -185,36 +165,11 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8;
if ([self isVisible] == enable)
return;
- contentAreaHasOffset_ = enable;
- [[self view] setHidden:enable ? NO : YES];
- [self applyContentAreaOffset:enable];
-
+ [resizeDelegate_ resizeView:[self view]
+ newHeight:(enable ? shelfHeight_ : 0)];
barIsVisible_ = enable;
}
-// Apply a contents box offset to make (or remove) room for the download shelf.
-// If apply is YES, always make room (the contentView_ is "full size"). If apply
-// is NO, we are trying to undo an offset. If no offset there is nothing to undo.
-- (void)applyContentAreaOffset:(BOOL)apply {
- if (!contentAreaHasOffset_ && apply) {
- // There is no offset to unconditionally apply.
- return;
- }
-
- NSRect frame = [contentArea_ frame];
- if (apply) {
- frame.origin.y += shelfHeight_;
- frame.size.height -= shelfHeight_;
- } else {
- frame.origin.y -= shelfHeight_;
- frame.size.height += shelfHeight_;
- }
-
- [[contentArea_ animator] setFrame:frame];
- [[self view] setNeedsDisplay:YES];
- [contentArea_ setNeedsDisplay:YES];
-}
-
- (DownloadShelf*)bridge {
return bridge_.get();
}
diff --git a/chrome/browser/cocoa/download_shelf_mac.mm b/chrome/browser/cocoa/download_shelf_mac.mm
index c415dc3..159ea06 100644
--- a/chrome/browser/cocoa/download_shelf_mac.mm
+++ b/chrome/browser/cocoa/download_shelf_mac.mm
@@ -13,7 +13,6 @@ DownloadShelfMac::DownloadShelfMac(Browser* browser,
DownloadShelfController* controller)
: browser_(browser),
shelf_controller_(controller) {
- Show();
}
void DownloadShelfMac::AddDownload(BaseDownloadItemModel* download_model) {
diff --git a/chrome/browser/cocoa/download_shelf_mac_unittest.mm b/chrome/browser/cocoa/download_shelf_mac_unittest.mm
index 78ff52d..1df20e3 100644
--- a/chrome/browser/cocoa/download_shelf_mac_unittest.mm
+++ b/chrome/browser/cocoa/download_shelf_mac_unittest.mm
@@ -57,19 +57,19 @@ class DownloadShelfMacTest : public testing::Test {
BrowserTestHelper browser_helper_;
};
-TEST_F(DownloadShelfMacTest, CreationCallsShow) {
+TEST_F(DownloadShelfMacTest, CreationDoesNotCallShow) {
// Also make sure the DownloadShelfMacTest constructor doesn't crash.
DownloadShelfMac shelf(browser_helper_.browser(),
(DownloadShelfController*)shelf_controller_.get());
- EXPECT_EQ(1, shelf_controller_.get()->callCountShow);
+ EXPECT_EQ(0, shelf_controller_.get()->callCountShow);
}
TEST_F(DownloadShelfMacTest, ForwardsShow) {
DownloadShelfMac shelf(browser_helper_.browser(),
(DownloadShelfController*)shelf_controller_.get());
- EXPECT_EQ(1, shelf_controller_.get()->callCountShow);
+ EXPECT_EQ(0, shelf_controller_.get()->callCountShow);
shelf.Show();
- EXPECT_EQ(2, shelf_controller_.get()->callCountShow);
+ EXPECT_EQ(1, shelf_controller_.get()->callCountShow);
}
TEST_F(DownloadShelfMacTest, ForwardsHide) {
diff --git a/chrome/browser/cocoa/find_bar_cocoa_controller.h b/chrome/browser/cocoa/find_bar_cocoa_controller.h
index 933f88e..13837de 100644
--- a/chrome/browser/cocoa/find_bar_cocoa_controller.h
+++ b/chrome/browser/cocoa/find_bar_cocoa_controller.h
@@ -40,8 +40,9 @@ class FindNotificationDetails;
- (IBAction)previousResult:(id)sender;
-// Positions the find bar based on the location of |contentArea|.
-- (void)positionFindBarView:(NSView*)contentArea;
+// Positions the find bar based on the location of the infobar container.
+// TODO(rohitrao): Move this logic into BrowserWindowController.
+- (void)positionFindBarView:(NSView*)infoBarContainerView;
// Methods called from FindBarBridge.
- (void)showFindBar;
diff --git a/chrome/browser/cocoa/find_bar_cocoa_controller.mm b/chrome/browser/cocoa/find_bar_cocoa_controller.mm
index f28fd56..15b53d6 100644
--- a/chrome/browser/cocoa/find_bar_cocoa_controller.mm
+++ b/chrome/browser/cocoa/find_bar_cocoa_controller.mm
@@ -52,21 +52,23 @@
true, false);
}
-// Positions the find bar view in the correct location based on the
-// current state of the window. Currently only the visibility of the
-// bookmark bar can affect the find bar's position.
-- (void)positionFindBarView:(NSView*)contentArea {
+// Positions the find bar view in the correct location based on the current
+// state of the window. The findbar is always positioned one pixel above the
+// infobar container. Note that we are using the infobar container location as
+// a proxy for the toolbar location, but we cannot position based on the toolbar
+// because the toolbar is not always present (for example in fullscreen
+// windows).
+- (void)positionFindBarView:(NSView*)infoBarContainerView {
static const int kRightEdgeOffset = 25;
NSView* findBarView = [self view];
int findBarHeight = NSHeight([findBarView frame]);
int findBarWidth = NSWidth([findBarView frame]);
- // Start by computing the upper right corner of the tab content
- // area, then move left by a constant offset and up one pixel. This
- // gives us the upper right corner of our bounding box. We move up
- // one pixel to overlap with the toolbar area, which allows us to
- // cover up the toolbar's border.
- NSRect windowRect = [contentArea frame];
+ // Start by computing the upper right corner of the infobar container, then
+ // move left by a constant offset and up one pixel. This gives us the upper
+ // right corner of our bounding box. We move up one pixel to overlap with the
+ // toolbar area, which allows us to cover up the toolbar's border, if present.
+ NSRect windowRect = [infoBarContainerView frame];
int max_x = NSMaxX(windowRect) - kRightEdgeOffset;
int max_y = NSMaxY(windowRect) + 1;
diff --git a/chrome/browser/cocoa/infobar_container_controller.h b/chrome/browser/cocoa/infobar_container_controller.h
index a565a10..cfd7157 100644
--- a/chrome/browser/cocoa/infobar_container_controller.h
+++ b/chrome/browser/cocoa/infobar_container_controller.h
@@ -6,9 +6,9 @@
#include "base/scoped_nsobject.h"
#include "base/scoped_ptr.h"
+#import "chrome/browser/cocoa/view_resizer.h"
#include "chrome/common/notification_registrar.h"
-@class BrowserWindowController;
class InfoBarDelegate;
class InfoBarNotificationObserver;
class TabContents;
@@ -22,8 +22,8 @@ class TabStripModelObserverBridge;
// adding/removing infobars when needed.
@interface InfoBarContainerController : NSViewController {
@private
- // Needed to send infoBarResized: messages when infobars are added or removed.
- BrowserWindowController* browserController_; // weak, owns us.
+ // Needed to send resize messages when infobars are added or removed.
+ id<ViewResizer> resizeDelegate_; // weak
// The TabContents we are currently showing infobars for.
TabContents* currentTabContents_; // weak
@@ -42,7 +42,7 @@ class TabStripModelObserverBridge;
}
- (id)initWithTabStripModel:(TabStripModel*)model
- browserWindowController:(BrowserWindowController*)controller;
+ resizeDelegate:(id<ViewResizer>)resizeDelegate;
// Informs the selected TabContents that the infobars for the given
// |delegate| need to be removed. Does not remove any infobar views
diff --git a/chrome/browser/cocoa/infobar_container_controller.mm b/chrome/browser/cocoa/infobar_container_controller.mm
index 06eaf67..4acc324 100644
--- a/chrome/browser/cocoa/infobar_container_controller.mm
+++ b/chrome/browser/cocoa/infobar_container_controller.mm
@@ -4,7 +4,6 @@
#include "base/logging.h"
#include "base/mac_util.h"
-#import "chrome/browser/cocoa/browser_window_controller.h"
#include "chrome/browser/cocoa/infobar.h"
#import "chrome/browser/cocoa/infobar_container_controller.h"
#import "chrome/browser/cocoa/infobar_controller.h"
@@ -64,11 +63,11 @@ class InfoBarNotificationObserver : public NotificationObserver {
@implementation InfoBarContainerController
- (id)initWithTabStripModel:(TabStripModel*)model
- browserWindowController:(BrowserWindowController*)controller {
- DCHECK(controller);
+ resizeDelegate:(id<ViewResizer>)resizeDelegate {
+ DCHECK(resizeDelegate);
if ((self = [super initWithNibName:@"InfoBarContainer"
bundle:mac_util::MainAppBundle()])) {
- browserController_ = controller;
+ resizeDelegate_ = resizeDelegate;
tabObserver_.reset(new TabStripModelObserverBridge(model, self));
infoBarObserver_.reset(new InfoBarNotificationObserver(self));
@@ -185,7 +184,7 @@ class InfoBarNotificationObserver : public NotificationObserver {
[view setFrame:frame];
}
- [browserController_ infoBarResized:[self desiredHeight]];
+ [resizeDelegate_ resizeView:[self view] newHeight:[self desiredHeight]];
}
@end
diff --git a/chrome/browser/cocoa/infobar_container_controller_unittest.mm b/chrome/browser/cocoa/infobar_container_controller_unittest.mm
index 77e8e82..b50e7d4 100644
--- a/chrome/browser/cocoa/infobar_container_controller_unittest.mm
+++ b/chrome/browser/cocoa/infobar_container_controller_unittest.mm
@@ -7,44 +7,21 @@
#include "base/scoped_nsautorelease_pool.h"
#include "base/scoped_nsobject.h"
#include "chrome/browser/cocoa/browser_test_helper.h"
-#import "chrome/browser/cocoa/browser_window_controller.h"
#import "chrome/browser/cocoa/cocoa_test_helper.h"
#import "chrome/browser/cocoa/infobar_container_controller.h"
#include "chrome/browser/cocoa/infobar_test_helper.h"
+#import "chrome/browser/cocoa/view_resizer_pong.h"
#include "testing/gtest/include/gtest/gtest.h"
-// Objective-C classes must be defined outside the namespace.
-@interface BrowserWindowControllerPong : BrowserWindowController {
- BOOL pong_;
-}
-@property(readonly) BOOL pong;
-@end
-
-@implementation BrowserWindowControllerPong
-@synthesize pong = pong_;
-
-- (id)initWithBrowser:(Browser*)browser {
- if ((self = [super initWithBrowser:browser takeOwnership:NO])) {
- pong_ = NO;
- }
- return self;
-}
-
-- (void)infoBarResized:(float)newHeight {
- pong_ = TRUE;
-}
-@end
-
namespace {
class InfoBarContainerControllerTest : public testing::Test {
virtual void SetUp() {
- browserController_.reset([[BrowserWindowControllerPong alloc]
- initWithBrowser:browser_helper_.browser()]);
+ resizeDelegate_.reset([[ViewResizerPong alloc] init]);
TabStripModel* model = browser_helper_.browser()->tabstrip_model();
controller_.reset([[InfoBarContainerController alloc]
initWithTabStripModel:model
- browserWindowController:browserController_]);
+ resizeDelegate:resizeDelegate_.get()]);
}
public:
@@ -54,7 +31,7 @@ class InfoBarContainerControllerTest : public testing::Test {
CocoaTestHelper cocoa_helper_;
BrowserTestHelper browser_helper_;
base::ScopedNSAutoreleasePool pool_;
- scoped_nsobject<BrowserWindowControllerPong> browserController_;
+ scoped_nsobject<ViewResizerPong> resizeDelegate_;
scoped_nsobject<InfoBarContainerController> controller_;
};
@@ -67,9 +44,11 @@ TEST_F(InfoBarContainerControllerTest, Show) {
}
TEST_F(InfoBarContainerControllerTest, BWCPong) {
- // Call positionInfoBarsAndResize and check that the BWC got a resize message.
+ // Call positionInfoBarsAndResize and check that |resizeDelegate_| got a
+ // resize message.
+ [resizeDelegate_ setHeight:-1];
[controller_ positionInfoBarsAndRedraw];
- EXPECT_TRUE([browserController_ pong]);
+ EXPECT_NE(-1, [resizeDelegate_ height]);
}
TEST_F(InfoBarContainerControllerTest, AddAndRemoveInfoBars) {
diff --git a/chrome/browser/cocoa/toolbar_controller.h b/chrome/browser/cocoa/toolbar_controller.h
index 07ec3e7..0e33048 100644
--- a/chrome/browser/cocoa/toolbar_controller.h
+++ b/chrome/browser/cocoa/toolbar_controller.h
@@ -11,6 +11,7 @@
#include "base/scoped_nsobject.h"
#import "chrome/browser/cocoa/command_observer_bridge.h"
#import "chrome/browser/cocoa/bookmark_bar_controller.h"
+#import "chrome/browser/cocoa/view_resizer.h"
#include "chrome/common/pref_member.h"
@class AutocompleteTextField;
@@ -31,7 +32,8 @@ class ToolbarView;
// Manages the bookmark bar and it's position in the window relative to
// the web content view.
-@interface ToolbarController : NSViewController<CommandObserverProtocol> {
+@interface ToolbarController :
+ NSViewController<CommandObserverProtocol, ViewResizer> {
@private
ToolbarModel* toolbarModel_; // weak, one per window
CommandUpdater* commands_; // weak, one per window
@@ -40,9 +42,8 @@ class ToolbarView;
scoped_ptr<LocationBarViewMac> locationBarView_;
scoped_nsobject<AutocompleteTextFieldEditor> autocompleteTextFieldEditor_;
scoped_nsobject<BookmarkBarController> bookmarkBarController_;
+ id<ViewResizer> resizeDelegate_; // weak
id<BookmarkURLOpener> bookmarkBarDelegate_; // weak
- NSView* webContentView_; // weak; where the web goes
- NSView* infoBarsView_; // weak; where the infobars go
// Used for monitoring the optional toolbar button prefs.
scoped_ptr<ToolbarControllerInternal::PrefObserverBridge> prefObserver_;
@@ -76,8 +77,7 @@ class ToolbarView;
- (id)initWithModel:(ToolbarModel*)model
commands:(CommandUpdater*)commands
profile:(Profile*)profile
- webContentView:(NSView*)webContentView
- infoBarsView:(NSView*)infoBarsView
+ resizeDelegate:(id<ViewResizer>)resizeDelegate
bookmarkDelegate:(id<BookmarkURLOpener>)delegate;
// Get the C++ bridge object representing the location bar for this tab.
diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm
index b5bc147..c999764 100644
--- a/chrome/browser/cocoa/toolbar_controller.mm
+++ b/chrome/browser/cocoa/toolbar_controller.mm
@@ -23,6 +23,12 @@
// Name of image in the bundle for the yellow of the star icon.
static NSString* const kStarredImageName = @"starred.pdf";
+// Height of the toolbar in pixels when the bookmark bar is closed.
+static const float kBaseToolbarHeight = 39.0;
+
+// Overlap (in pixels) between the toolbar and the bookmark bar.
+static const float kBookmarkBarOverlap = 5.0;
+
@interface ToolbarController(Private)
- (void)initCommandStatus:(CommandUpdater*)commands;
- (void)prefChanged:(std::wstring*)prefName;
@@ -54,8 +60,7 @@ class PrefObserverBridge : public NotificationObserver {
- (id)initWithModel:(ToolbarModel*)model
commands:(CommandUpdater*)commands
profile:(Profile*)profile
- webContentView:(NSView*)webContentView
- infoBarsView:(NSView*)infoBarsView
+ resizeDelegate:(id<ViewResizer>)resizeDelegate
bookmarkDelegate:(id<BookmarkURLOpener>)delegate {
DCHECK(model && commands && profile);
if ((self = [super initWithNibName:@"Toolbar"
@@ -63,9 +68,8 @@ class PrefObserverBridge : public NotificationObserver {
toolbarModel_ = model;
commands_ = commands;
profile_ = profile;
+ resizeDelegate_ = resizeDelegate;
bookmarkBarDelegate_ = delegate;
- webContentView_ = webContentView;
- infoBarsView_ = infoBarsView;
hasToolbar_ = YES;
// Register for notifications about state changes for the toolbar buttons
@@ -109,10 +113,9 @@ class PrefObserverBridge : public NotificationObserver {
// Create a sub-controller for the bookmark bar.
bookmarkBarController_.reset([[BookmarkBarController alloc]
initWithProfile:profile_
- parentView:[self view]
- webContentView:webContentView_
- infoBarsView:infoBarsView_
- delegate:bookmarkBarDelegate_]);
+ initialWidth:NSWidth([[self view] frame])
+ resizeDelegate:self
+ urlDelegate:bookmarkBarDelegate_]);
// Add bookmark bar to the view hierarchy. This also triggers the
// nib load. The bookmark bar is defined (in the nib) to be
@@ -131,6 +134,22 @@ class PrefObserverBridge : public NotificationObserver {
locationBarRetainer_.reset([locationBar_ retain]);
}
+- (void)resizeView:(NSView*)view newHeight:(float)height {
+ DCHECK(view == [bookmarkBarController_ view]);
+
+ // The bookmark bar is always rooted at the bottom of the toolbar view, with
+ // width equal to the toolbar's width. The toolbar view is resized to
+ // accomodate the new bookmark bar height.
+ NSRect frame = NSMakeRect(0, 0, [[self view] bounds].size.width, height);
+ [view setFrame:frame];
+
+ float newToolbarHeight = kBaseToolbarHeight + height - kBookmarkBarOverlap;
+ if (newToolbarHeight < kBaseToolbarHeight)
+ newToolbarHeight = kBaseToolbarHeight;
+
+ [resizeDelegate_ resizeView:[self view] newHeight:newToolbarHeight];
+}
+
- (LocationBar*)locationBar {
return locationBarView_.get();
}
diff --git a/chrome/browser/cocoa/toolbar_controller_unittest.mm b/chrome/browser/cocoa/toolbar_controller_unittest.mm
index 9690c5b..a82212b 100644
--- a/chrome/browser/cocoa/toolbar_controller_unittest.mm
+++ b/chrome/browser/cocoa/toolbar_controller_unittest.mm
@@ -9,6 +9,7 @@
#include "chrome/browser/cocoa/browser_test_helper.h"
#import "chrome/browser/cocoa/cocoa_test_helper.h"
#import "chrome/browser/cocoa/toolbar_controller.h"
+#import "chrome/browser/cocoa/view_resizer_pong.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -32,12 +33,12 @@ class ToolbarControllerTest : public testing::Test {
// ensure they get picked up correct on initialization
updater->UpdateCommandEnabled(IDC_BACK, false);
updater->UpdateCommandEnabled(IDC_FORWARD, false);
+ resizeDelegate_.reset([[ViewResizerPong alloc] init]);
bar_.reset(
[[ToolbarController alloc] initWithModel:browser->toolbar_model()
commands:browser->command_updater()
profile:helper_.profile()
- webContentView:nil
- infoBarsView:nil
+ resizeDelegate:resizeDelegate_.get()
bookmarkDelegate:nil]);
EXPECT_TRUE([bar_ view]);
NSView* parent = [cocoa_helper_.window() contentView];
@@ -61,6 +62,7 @@ class ToolbarControllerTest : public testing::Test {
CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc...
BrowserTestHelper helper_;
+ scoped_nsobject<ViewResizerPong> resizeDelegate_;
scoped_nsobject<ToolbarController> bar_;
};
@@ -192,4 +194,32 @@ TEST_F(ToolbarControllerTest, TogglePageWrench) {
EXPECT_NE(NSWidth(originalLocationBarFrame), NSWidth([locationBar frame]));
}
+TEST_F(ToolbarControllerTest, BookmarkBarResizes) {
+ NSView* bookmarkBarView = [[bar_ bookmarkBarController] view];
+ ASSERT_EQ(0, NSHeight([bookmarkBarView frame]));
+ [resizeDelegate_ setHeight:-1];
+
+ // Resize the bookmarkbar to 30px. The toolbar should ask the delegate to
+ // resize to 64px.
+ [bar_ resizeView:bookmarkBarView newHeight:30];
+ EXPECT_EQ(64, [resizeDelegate_ height]);
+ EXPECT_EQ(30, NSHeight([bookmarkBarView frame]));
+
+ // Resize the bookmarkbar back to 0px. Toolbar should be at 39px.
+ [bar_ resizeView:bookmarkBarView newHeight:0];
+ EXPECT_EQ(39, [resizeDelegate_ height]);
+ EXPECT_EQ(0, NSHeight([bookmarkBarView frame]));
+
+ // Resize the bookmarkbar to 5px. Toolbar should stay at 39px.
+ [resizeDelegate_ setHeight:-1];
+ [bar_ resizeView:bookmarkBarView newHeight:5];
+ EXPECT_EQ(39, [resizeDelegate_ height]);
+ EXPECT_EQ(5, NSHeight([bookmarkBarView frame]));
+
+ // Resize the bookmarkbar to 6px. Toolbar should grow to 40px.
+ [bar_ resizeView:bookmarkBarView newHeight:6];
+ EXPECT_EQ(40, [resizeDelegate_ height]);
+ EXPECT_EQ(6, NSHeight([bookmarkBarView frame]));
+}
+
} // namespace
diff --git a/chrome/browser/cocoa/view_resizer.h b/chrome/browser/cocoa/view_resizer.h
new file mode 100644
index 0000000..199b60f
--- /dev/null
+++ b/chrome/browser/cocoa/view_resizer.h
@@ -0,0 +1,21 @@
+// 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_VIEW_RESIZER_H_
+#define CHROME_BROWSER_COCOA_VIEW_RESIZER_H_
+
+#include "chrome/browser/tabs/tab_strip_model.h"
+
+#import <Cocoa/Cocoa.h>
+
+// Defines a protocol that allows controllers to delegate resizing their views
+// to their parents. When a controller needs to change a view's height, rather
+// than resizing it directly, it sends a message to its parent asking the parent
+// to perform the resize. This allows the parent to do any re-layout that may
+// become necessary due to the resize.
+@protocol ViewResizer
+- (void)resizeView:(NSView*)view newHeight:(float)height;
+@end
+
+#endif // CHROME_BROWSER_COCOA_VIEW_RESIZER_H_
diff --git a/chrome/browser/cocoa/view_resizer_pong.h b/chrome/browser/cocoa/view_resizer_pong.h
new file mode 100644
index 0000000..0f3caf2
--- /dev/null
+++ b/chrome/browser/cocoa/view_resizer_pong.h
@@ -0,0 +1,21 @@
+// 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_VIEW_RESIZER_PONG_H_
+#define CHROME_BROWSER_COCOA_VIEW_RESIZER_PONG_H_
+
+#import <Cocoa/Cocoa.h>
+
+#import "chrome/browser/cocoa/view_resizer.h"
+
+@interface ViewResizerPong : NSObject<ViewResizer> {
+ @private
+ float height_;
+}
+@property float height;
+
+- (void)resizeView:(NSView*)view newHeight:(float)height;
+@end
+
+#endif // CHROME_BROWSER_COCOA_VIEW_RESIZER_PONG_H_
diff --git a/chrome/browser/cocoa/view_resizer_pong.mm b/chrome/browser/cocoa/view_resizer_pong.mm
new file mode 100644
index 0000000..9246af7
--- /dev/null
+++ b/chrome/browser/cocoa/view_resizer_pong.mm
@@ -0,0 +1,19 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "chrome/browser/cocoa/view_resizer_pong.h"
+
+@implementation ViewResizerPong
+
+@synthesize height = height_;
+
+- (void)resizeView:(NSView*)view newHeight:(float)height {
+ [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)];
+}
+@end
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 06eab55..c2eb3ea 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -876,6 +876,7 @@
'browser/cocoa/toolbar_view.mm',
'browser/cocoa/ui_localizer.h',
'browser/cocoa/ui_localizer.mm',
+ 'browser/cocoa/view_resizer.h',
'browser/cocoa/web_drag_source.h',
'browser/cocoa/web_drag_source.mm',
'browser/cocoa/web_drop_target.h',
@@ -3711,6 +3712,8 @@
'browser/cocoa/toolbar_controller_unittest.mm',
'browser/cocoa/toolbar_view_unittest.mm',
'browser/cocoa/ui_localizer_unittest.mm',
+ 'browser/cocoa/view_resizer_pong.h',
+ 'browser/cocoa/view_resizer_pong.mm',
'browser/cocoa/web_drop_target_unittest.mm',
'browser/command_updater_unittest.cc',
'browser/debugger/devtools_manager_unittest.cc',