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

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

Issue 155494: First cut at infobars on Mac. These are not expected to be... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 11 years, 5 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/cocoa/infobar_container_controller.mm
===================================================================
--- chrome/browser/cocoa/infobar_container_controller.mm (revision 0)
+++ chrome/browser/cocoa/infobar_container_controller.mm (revision 0)
@@ -0,0 +1,191 @@
+// 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.
+
+#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"
+#include "chrome/browser/cocoa/tab_strip_model_observer_bridge.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/notification_service.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 NotificationObserver {
+ public:
+ InfoBarNotificationObserver(InfoBarContainerController* controller)
+ : controller_(controller) {
+ }
+
+ private:
+ // NotificationObserver implementation
+ void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type.value) {
+ case NotificationType::TAB_CONTENTS_INFOBAR_ADDED:
+ [controller_ addInfoBar:Details<InfoBarDelegate>(details).ptr()];
+ break;
+ case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED:
+ [controller_
+ removeInfoBarsForDelegate:Details<InfoBarDelegate>(details).ptr()];
+ 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.
+- (float)desiredHeight;
+
+// Modifies this container to display infobars for the given
+// |contents|. Registers for INFOBAR_ADDED and INFOBAR_REMOVED
+// notifications for |contents|. If we are currently showing any
+// infobars, removes them first and deregisters for any
+// notifications. |contents| can be NULL, in which case no infobars
+// are shown and no notifications are registered for.
+- (void)changeTabContents:(TabContents*)contents;
+
+@end
+
+
+@implementation InfoBarContainerController
+- (id)initWithTabStripModel:(TabStripModel*)model
+ browserWindowController:(BrowserWindowController*)controller {
+ DCHECK(controller);
+ if ((self = [super initWithNibName:@"InfoBarContainer"
+ bundle:mac_util::MainAppBundle()])) {
+ browserController_ = controller;
+ tabObserver_.reset(new TabStripModelObserverBridge(model, self));
+ infoBarObserver_.reset(new InfoBarNotificationObserver(self));
+
+ // 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]);
+ }
+ return self;
+}
+
+- (void)dealloc {
+ DCHECK([infobarControllers_ count] == 0);
+ [super dealloc];
+}
+
+- (void)removeDelegate:(InfoBarDelegate*)delegate {
+ DCHECK(currentTabContents_);
+ currentTabContents_->RemoveInfoBar(delegate);
+}
+
+// TabStripModelObserverBridge notifications
+- (void)selectTabWithContents:(TabContents*)newContents
+ previousContents:(TabContents*)oldContents
+ atIndex:(NSInteger)index
+ userGesture:(bool)wasUserGesture {
+ [self changeTabContents:newContents];
+}
+
+- (void)tabDetachedWithContents:(TabContents*)contents
+ atIndex:(NSInteger)index {
+ [self changeTabContents:NULL];
+}
+
+@end
+
+@implementation InfoBarContainerController (PrivateMethods)
+
+- (float)desiredHeight {
+ float height = 0;
+
+ for (InfoBarController* controller in infobarControllers_.get()) {
+ height += [[controller view] frame].size.height;
+ }
+
+ return height;
+}
+
+- (void)changeTabContents:(TabContents*)contents {
+ registrar_.RemoveAll();
+ [self removeAllInfoBars];
+
+ currentTabContents_ = contents;
+ if (currentTabContents_) {
+ for (int i = 0; i < currentTabContents_->infobar_delegate_count(); ++i) {
+ [self addInfoBar:currentTabContents_->GetInfoBarDelegateAt(i)];
+ }
+
+ Source<TabContents> source(currentTabContents_);
+ registrar_.Add(infoBarObserver_.get(),
+ NotificationType::TAB_CONTENTS_INFOBAR_ADDED, source);
+ registrar_.Add(infoBarObserver_.get(),
+ NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, source);
+ }
+
+ [self positionInfoBarsAndRedraw];
+}
+
+- (void)addInfoBar:(InfoBarDelegate*)delegate {
+ scoped_ptr<InfoBar> infobar(delegate->CreateInfoBar());
+ InfoBarController* controller = infobar->controller();
+ [controller setContainerController:self];
+ [[self view] addSubview:[controller view]];
+ [infobarControllers_ addObject:[controller autorelease]];
+}
+
+- (void)removeInfoBarsForDelegate:(InfoBarDelegate*)delegate {
+ for (InfoBarController* controller in
+ [NSArray arrayWithArray:infobarControllers_.get()]) {
+ if ([controller delegate] == delegate) {
+ // This code can be executed while -[InfoBarController closeInfoBar] 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];
+ }
+ }
+}
+
+- (void)removeAllInfoBars {
+ for (InfoBarController* controller in infobarControllers_.get()) {
+ [[controller view] removeFromSuperview];
+ }
+ [infobarControllers_ removeAllObjects];
+}
+
+- (void)positionInfoBarsAndRedraw {
+ NSRect containerBounds = [[self view] bounds];
+ int minY = 0;
+
+ // Stack the infobars at the bottom of the view, starting with the
+ // last infobar and working our way to the front of the array. This
+ // way we ensure that the first infobar added shows up on top, with
+ // the others below.
+ for (InfoBarController* controller in
+ [infobarControllers_ reverseObjectEnumerator]) {
+ NSView* view = [controller view];
+ NSRect frame = [view frame];
+ frame.origin.x = NSMinX(containerBounds);
+ frame.size.width = NSWidth(containerBounds);
+ frame.origin.y = minY;
+ minY += frame.size.height;
+ // TODO(rohitrao, jrg): Replace with an animator.
+ [view setFrame:frame];
+ }
+
+ [browserController_ infoBarResized:[self desiredHeight]];
+}
+
+@end
Property changes on: chrome/browser/cocoa/infobar_container_controller.mm
___________________________________________________________________
Name: svn:eol-style
+ LF
« no previous file with comments | « chrome/browser/cocoa/infobar_container_controller.h ('k') | chrome/browser/cocoa/infobar_container_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698