Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Unified Diff: chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm

Issue 23338005: Mac InfoBar: Use cross platform infobar classes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm b/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm
index f68a15e51410d9eab97fb3c0cf067861a4d5c7f3..1e4368f070959de3c2b73b985b24ca1f717623af 100644
--- a/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm
+++ b/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm
@@ -3,81 +3,25 @@
// found in the LICENSE file.
#include "base/logging.h"
-#include "base/mac/bundle_locations.h"
#include "base/mac/mac_util.h"
-#include "chrome/browser/chrome_notification_types.h"
+#include "base/message_loop/message_loop.h"
#include "chrome/browser/infobars/confirm_infobar_delegate.h"
#include "chrome/browser/infobars/infobar.h"
+#include "chrome/browser/infobars/infobar_container.h"
#include "chrome/browser/infobars/infobar_service.h"
-#import "chrome/browser/ui/cocoa/animatable_view.h"
#import "chrome/browser/ui/cocoa/browser_window_controller.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_cocoa.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.h"
#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
#import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
+#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
#import "chrome/browser/ui/cocoa/view_id_util.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
-#include "skia/ext/skia_utils_mac.h"
-
-// C++ class that receives INFOBAR_ADDED and INFOBAR_REMOVED
-// notifications and proxies them back to |controller|.
-class InfoBarNotificationObserver : public content::NotificationObserver {
- public:
- InfoBarNotificationObserver(InfoBarContainerController* controller)
- : controller_(controller) {
- }
-
- private:
- // NotificationObserver implementation
- virtual void Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE {
- InfoBarService* infobar_service =
- content::Source<InfoBarService>(source).ptr();
- switch (type) {
- case chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED:
- [controller_ addInfoBar:content::Details<InfoBarAddedDetails>(details)->
- CreateInfoBar(infobar_service)
- animate:YES];
- break;
-
- case chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED: {
- InfoBarRemovedDetails* removed_details =
- content::Details<InfoBarRemovedDetails>(details).ptr();
- [controller_
- closeInfoBarsForDelegate:removed_details->first
- animate:(removed_details->second ? YES : NO)];
- break;
- }
-
- case chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED: {
- InfoBarReplacedDetails* replaced_details =
- content::Details<InfoBarReplacedDetails>(details).ptr();
- [controller_ closeInfoBarsForDelegate:replaced_details->first
- animate:NO];
- [controller_ addInfoBar:replaced_details->second->
- CreateInfoBar(infobar_service)
- animate:NO];
- break;
- }
-
- default:
- NOTREACHED(); // we don't ask for anything else!
- break;
- }
-
- [controller_ positionInfoBarsAndRedraw];
- }
-
- InfoBarContainerController* controller_; // weak, owns us.
-};
-
-
-@interface InfoBarContainerController (PrivateMethods)
-// Returns the desired height of the container view, computed by
-// adding together the heights of all its subviews.
-- (CGFloat)desiredHeight;
+@interface InfoBarContainerController()
Robert Sesek 2013/08/26 14:06:56 nit: space before (
sail 2013/08/26 18:32:23 Done.
+// Removes |controller| from the list of controllers in this container and
+// removes its view from the view hierarchy. This method is safe to call while
+// |controller| is still on the call stack.
+- (void)removeController:(InfoBarController*)controller;
@end
@@ -87,50 +31,27 @@ class InfoBarNotificationObserver : public content::NotificationObserver {
- (id)initWithResizeDelegate:(id<ViewResizer>)resizeDelegate {
DCHECK(resizeDelegate);
- if ((self = [super initWithNibName:@"InfoBarContainer"
- bundle:base::mac::FrameworkBundle()])) {
- resizeDelegate_ = resizeDelegate;
- infoBarObserver_.reset(new InfoBarNotificationObserver(self));
+ if ((self = [super init])) {
Robert Sesek 2013/08/26 14:06:56 Don't you need to call through -initWithNibName:bu
sail 2013/08/26 18:32:23 Done.
+ base::scoped_nsobject<NSView> view(
+ [[NSView alloc] initWithFrame:NSZeroRect]);
+ [view setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin];
+ view_id_util::SetID(view, VIEW_ID_INFO_BAR_CONTAINER);
+ [self setView:view];
- // NSMutableArray needs an initial capacity, and we rarely ever see
- // more than two infobars at a time, so that seems like a good choice.
- infobarControllers_.reset([[NSMutableArray alloc] initWithCapacity:2]);
- closingInfoBars_.reset([[NSMutableSet alloc] initWithCapacity:2]);
+ resizeDelegate_ = resizeDelegate;
+ containerCocoa_.reset(new InfoBarContainerCocoa(self));
+ infobarControllers_.reset([[NSMutableArray alloc] init]);
}
return self;
}
- (void)dealloc {
+ containerCocoa_.reset();
Robert Sesek 2013/08/26 14:06:56 Why does this need to be done explicitly?
sail 2013/08/26 18:32:23 Done. Documented.
DCHECK_EQ([infobarControllers_ count], 0U);
- DCHECK_EQ([closingInfoBars_ count], 0U);
view_id_util::UnsetID([self view]);
[super dealloc];
}
-- (void)awakeFromNib {
- // The info bar container view is an ordinary NSView object, so we set its
- // ViewID here.
- view_id_util::SetID([self view], VIEW_ID_INFO_BAR_CONTAINER);
-}
-
-- (void)willRemoveController:(InfoBarController*)controller {
- [closingInfoBars_ addObject:controller];
-}
-
-- (void)removeController:(InfoBarController*)controller {
- if (![infobarControllers_ containsObject:controller])
- return;
-
- // This code can be executed while InfoBarController is still on the stack, so
- // we retain and autorelease the controller to prevent it from being
- // dealloc'ed too early.
- [[controller retain] autorelease];
- [[controller view] removeFromSuperview];
- [infobarControllers_ removeObject:controller];
- [closingInfoBars_ removeObject:controller];
- [self positionInfoBarsAndRedraw];
-}
-
- (BrowserWindowController*)browserWindowController {
id controller = [[[self view] window] windowController];
if (![controller isKindOfClass:[BrowserWindowController class]])
@@ -138,30 +59,19 @@ class InfoBarNotificationObserver : public content::NotificationObserver {
return controller;
}
-- (void)changeWebContents:(content::WebContents*)contents {
- registrar_.RemoveAll();
- [self removeAllInfoBars];
-
- currentWebContents_ = contents;
- if (currentWebContents_) {
- InfoBarService* infobarService =
- InfoBarService::FromWebContents(currentWebContents_);
- for (size_t i = 0; i < infobarService->infobar_count(); ++i) {
- InfoBar* infobar =
- infobarService->infobar_at(i)->CreateInfoBar(infobarService);
- [self addInfoBar:infobar animate:NO];
- }
+- (CGFloat)infobarArrowX {
+ LocationBarViewMac* locationBar =
+ [[self browserWindowController] locationBarBridge];
+ return locationBar->GetPageInfoBubblePoint().x;
+}
- content::Source<InfoBarService> source(infobarService);
- registrar_.Add(infoBarObserver_.get(),
- chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, source);
- registrar_.Add(infoBarObserver_.get(),
- chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, source);
- registrar_.Add(infoBarObserver_.get(),
- chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED, source);
+- (void)changeWebContents:(content::WebContents*)contents {
+ if (contents) {
+ containerCocoa_->ChangeInfoBarService(
+ InfoBarService::FromWebContents(contents));
+ } else {
+ containerCocoa_->ChangeInfoBarService(NULL);
}
-
- [self positionInfoBarsAndRedraw];
}
- (void)tabDetachedWithContents:(content::WebContents*)contents {
@@ -169,99 +79,37 @@ class InfoBarNotificationObserver : public content::NotificationObserver {
[self changeWebContents:NULL];
}
-- (NSUInteger)infobarCount {
- return [infobarControllers_ count] - [closingInfoBars_ count];
-}
-
- (CGFloat)overlappingTipHeight {
- return [self infobarCount] ? infobars::kTipHeight : 0;
-}
-
-- (void)resizeView:(NSView*)view newHeight:(CGFloat)height {
- NSRect frame = [view frame];
- frame.size.height = height;
- [view setFrame:frame];
- [self positionInfoBarsAndRedraw];
-}
-
-- (void)setAnimationInProgress:(BOOL)inProgress {
- if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
- [resizeDelegate_ setAnimationInProgress:inProgress];
-}
-
-- (void)setShouldSuppressTopInfoBarTip:(BOOL)flag {
- if (shouldSuppressTopInfoBarTip_ == flag)
- return;
- shouldSuppressTopInfoBarTip_ = flag;
- [self positionInfoBarsAndRedraw];
-}
-
-@end
-
-@implementation InfoBarContainerController (PrivateMethods)
-
-- (CGFloat)desiredHeight {
- CGFloat height = 0;
-
- // Take out the height of the tip from the total size of the infobar so that
- // the tip overlaps the preceding infobar when there is more than one infobar.
- for (InfoBarController* controller in infobarControllers_.get())
- height += NSHeight([[controller view] frame]) - infobars::kTipHeight;
-
- // If there are any infobars, add a little extra room for the tip of the first
- // infobar.
- if (height)
- height += infobars::kTipHeight;
-
- return height;
+ return containerCocoa_->GetVerticalOverlap(NULL);
}
-- (void)addInfoBar:(InfoBar*)infobar animate:(BOOL)animate {
+- (void)addInfoBar:(InfoBarCocoa*)infobar
+ position:(NSUInteger)position {
InfoBarController* controller = infobar->controller();
[controller setContainerController:self];
- [[controller animatableView] setResizeDelegate:self];
- [[self view] addSubview:[controller view]];
- [infobarControllers_ addObject:[controller autorelease]];
+ [infobarControllers_ insertObject:controller atIndex:position];
- if (animate)
- [controller animateOpen];
- else
- [controller open];
-
- delete infobar;
+ NSView* relativeView = nil;
+ if (position > 0)
+ relativeView = [[infobarControllers_ objectAtIndex:position - 1] view];
+ [[self view] addSubview:[controller view]
+ positioned:NSWindowAbove
+ relativeTo:relativeView];
}
-- (void)closeInfoBarsForDelegate:(InfoBarDelegate*)delegate
- animate:(BOOL)animate {
- for (InfoBarController* controller in
- [NSArray arrayWithArray:infobarControllers_.get()]) {
- if ([controller delegate] == delegate) {
- [controller infobarWillClose];
- if (animate)
- [controller animateClosed];
- else
- [controller close];
- }
- }
+- (void)removeInfoBar:(InfoBarCocoa*)infobar {
+ [infobar->controller() infobarWillClose];
+ [self removeController:infobar->controller()];
+ base::MessageLoop::current()->DeleteSoon(FROM_HERE, infobar);
}
-- (void)removeAllInfoBars {
- // stopAnimation can remove the infobar from infobarControllers_ if it was in
- // the midst of closing, so copy the array so mutations won't cause problems.
- for (InfoBarController* controller in
- [NSArray arrayWithArray:infobarControllers_.get()]) {
- [[controller animatableView] stopAnimation];
- // This code can be executed while InfoBarController is still on the stack,
- // so we retain and autorelease the controller to prevent it from being
- // dealloc'ed too early.
- [[controller retain] autorelease];
- [[controller view] removeFromSuperview];
+- (void)positionInfoBarsAndRedraw:(BOOL)isAnimating {
+ if (isAnimating_ != isAnimating) {
+ isAnimating_ = isAnimating;
+ if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
+ [resizeDelegate_ setAnimationInProgress:isAnimating_];
}
- [infobarControllers_ removeAllObjects];
- [closingInfoBars_ removeAllObjects];
-}
-- (void)positionInfoBarsAndRedraw {
NSRect containerBounds = [[self view] bounds];
int minY = 0;
@@ -271,20 +119,47 @@ class InfoBarNotificationObserver : public content::NotificationObserver {
// the others below.
for (InfoBarController* controller in
[infobarControllers_ reverseObjectEnumerator]) {
- NSView* view = [controller view];
- NSRect frame = [view frame];
+ NSRect frame;
frame.origin.x = NSMinX(containerBounds);
frame.origin.y = minY;
frame.size.width = NSWidth(containerBounds);
- [view setFrame:frame];
+ frame.size.height = [controller infobar]->total_height();
+ [[controller view] setFrame:frame];
- minY += NSHeight(frame) - infobars::kTipHeight;
+ minY += NSHeight(frame) - [controller infobar]->arrow_height();
+ [controller layoutArrow];
+ }
+
+ int totalHeight = 0;
+ int overlap = containerCocoa_->GetVerticalOverlap(&totalHeight);
- BOOL isTop = [controller isEqual:[infobarControllers_ objectAtIndex:0]];
- [controller setHasTip:!shouldSuppressTopInfoBarTip_ || !isTop];
+ if (NSHeight([[self view] frame]) != totalHeight) {
+ [resizeDelegate_ resizeView:[self view] newHeight:totalHeight];
+ } else if (oldOverlappingTipHeight_ != overlap) {
+ // If the infobar overlap changed but the height didn't change then
+ // explicitly ask for a layout.
+ oldOverlappingTipHeight_ = overlap;
+ [[self browserWindowController] layoutInfoBar];
}
+}
+
+- (void)setShouldSuppressTopInfoBarTip:(BOOL)flag {
+ if (shouldSuppressTopInfoBarTip_ == flag)
+ return;
+ shouldSuppressTopInfoBarTip_ = flag;
+ [self positionInfoBarsAndRedraw:isAnimating_];
+}
- [resizeDelegate_ resizeView:[self view] newHeight:[self desiredHeight]];
+- (void)removeController:(InfoBarController*)controller {
+ if (![infobarControllers_ containsObject:controller])
+ return;
+
+ // This code can be executed while InfoBarController is still on the stack, so
+ // we retain and autorelease the controller to prevent it from being
+ // dealloc'ed too early.
+ [[controller retain] autorelease];
+ [[controller view] removeFromSuperview];
+ [infobarControllers_ removeObject:controller];
}
@end

Powered by Google App Engine
This is Rietveld 408576698