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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
Property Changes:
Name: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/logging.h"
6 #include "base/mac_util.h"
7 #import "chrome/browser/cocoa/browser_window_controller.h"
8 #include "chrome/browser/cocoa/infobar.h"
9 #import "chrome/browser/cocoa/infobar_container_controller.h"
10 #import "chrome/browser/cocoa/infobar_controller.h"
11 #include "chrome/browser/cocoa/tab_strip_model_observer_bridge.h"
12 #include "chrome/browser/tab_contents/tab_contents.h"
13 #include "chrome/common/notification_service.h"
14 #include "skia/ext/skia_utils_mac.h"
15
16 // C++ class that receives INFOBAR_ADDED and INFOBAR_REMOVED
17 // notifications and proxies them back to |controller|.
18 class InfoBarNotificationObserver : public NotificationObserver {
19 public:
20 InfoBarNotificationObserver(InfoBarContainerController* controller)
21 : controller_(controller) {
22 }
23
24 private:
25 // NotificationObserver implementation
26 void Observe(NotificationType type,
27 const NotificationSource& source,
28 const NotificationDetails& details) {
29 switch (type.value) {
30 case NotificationType::TAB_CONTENTS_INFOBAR_ADDED:
31 [controller_ addInfoBar:Details<InfoBarDelegate>(details).ptr()];
32 break;
33 case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED:
34 [controller_
35 removeInfoBarsForDelegate:Details<InfoBarDelegate>(details).ptr()];
36 break;
37 default:
38 NOTREACHED(); // we don't ask for anything else!
39 break;
40 }
41
42 [controller_ positionInfoBarsAndRedraw];
43 }
44
45 InfoBarContainerController* controller_; // weak, owns us.
46 };
47
48
49 @interface InfoBarContainerController (PrivateMethods)
50 // Returns the desired height of the container view, computed by
51 // adding together the heights of all its subviews.
52 - (float)desiredHeight;
53
54 // Modifies this container to display infobars for the given
55 // |contents|. Registers for INFOBAR_ADDED and INFOBAR_REMOVED
56 // notifications for |contents|. If we are currently showing any
57 // infobars, removes them first and deregisters for any
58 // notifications. |contents| can be NULL, in which case no infobars
59 // are shown and no notifications are registered for.
60 - (void)changeTabContents:(TabContents*)contents;
61
62 @end
63
64
65 @implementation InfoBarContainerController
66 - (id)initWithTabStripModel:(TabStripModel*)model
67 browserWindowController:(BrowserWindowController*)controller {
68 DCHECK(controller);
69 if ((self = [super initWithNibName:@"InfoBarContainer"
70 bundle:mac_util::MainAppBundle()])) {
71 browserController_ = controller;
72 tabObserver_.reset(new TabStripModelObserverBridge(model, self));
73 infoBarObserver_.reset(new InfoBarNotificationObserver(self));
74
75 // NSMutableArray needs an initial capacity, and we rarely ever see
76 // more than two infobars at a time, so that seems like a good choice.
77 infobarControllers_.reset([[NSMutableArray alloc] initWithCapacity:2]);
78 }
79 return self;
80 }
81
82 - (void)dealloc {
83 DCHECK([infobarControllers_ count] == 0);
84 [super dealloc];
85 }
86
87 - (void)removeDelegate:(InfoBarDelegate*)delegate {
88 DCHECK(currentTabContents_);
89 currentTabContents_->RemoveInfoBar(delegate);
90 }
91
92 // TabStripModelObserverBridge notifications
93 - (void)selectTabWithContents:(TabContents*)newContents
94 previousContents:(TabContents*)oldContents
95 atIndex:(NSInteger)index
96 userGesture:(bool)wasUserGesture {
97 [self changeTabContents:newContents];
98 }
99
100 - (void)tabDetachedWithContents:(TabContents*)contents
101 atIndex:(NSInteger)index {
102 [self changeTabContents:NULL];
103 }
104
105 @end
106
107 @implementation InfoBarContainerController (PrivateMethods)
108
109 - (float)desiredHeight {
110 float height = 0;
111
112 for (InfoBarController* controller in infobarControllers_.get()) {
113 height += [[controller view] frame].size.height;
114 }
115
116 return height;
117 }
118
119 - (void)changeTabContents:(TabContents*)contents {
120 registrar_.RemoveAll();
121 [self removeAllInfoBars];
122
123 currentTabContents_ = contents;
124 if (currentTabContents_) {
125 for (int i = 0; i < currentTabContents_->infobar_delegate_count(); ++i) {
126 [self addInfoBar:currentTabContents_->GetInfoBarDelegateAt(i)];
127 }
128
129 Source<TabContents> source(currentTabContents_);
130 registrar_.Add(infoBarObserver_.get(),
131 NotificationType::TAB_CONTENTS_INFOBAR_ADDED, source);
132 registrar_.Add(infoBarObserver_.get(),
133 NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, source);
134 }
135
136 [self positionInfoBarsAndRedraw];
137 }
138
139 - (void)addInfoBar:(InfoBarDelegate*)delegate {
140 scoped_ptr<InfoBar> infobar(delegate->CreateInfoBar());
141 InfoBarController* controller = infobar->controller();
142 [controller setContainerController:self];
143 [[self view] addSubview:[controller view]];
144 [infobarControllers_ addObject:[controller autorelease]];
145 }
146
147 - (void)removeInfoBarsForDelegate:(InfoBarDelegate*)delegate {
148 for (InfoBarController* controller in
149 [NSArray arrayWithArray:infobarControllers_.get()]) {
150 if ([controller delegate] == delegate) {
151 // This code can be executed while -[InfoBarController closeInfoBar] is
152 // still on the stack, so we retain and autorelease the controller to
153 // prevent it from being dealloc'ed too early.
154 [[controller retain] autorelease];
155 [[controller view] removeFromSuperview];
156 [infobarControllers_ removeObject:controller];
157 }
158 }
159 }
160
161 - (void)removeAllInfoBars {
162 for (InfoBarController* controller in infobarControllers_.get()) {
163 [[controller view] removeFromSuperview];
164 }
165 [infobarControllers_ removeAllObjects];
166 }
167
168 - (void)positionInfoBarsAndRedraw {
169 NSRect containerBounds = [[self view] bounds];
170 int minY = 0;
171
172 // Stack the infobars at the bottom of the view, starting with the
173 // last infobar and working our way to the front of the array. This
174 // way we ensure that the first infobar added shows up on top, with
175 // the others below.
176 for (InfoBarController* controller in
177 [infobarControllers_ reverseObjectEnumerator]) {
178 NSView* view = [controller view];
179 NSRect frame = [view frame];
180 frame.origin.x = NSMinX(containerBounds);
181 frame.size.width = NSWidth(containerBounds);
182 frame.origin.y = minY;
183 minY += frame.size.height;
184 // TODO(rohitrao, jrg): Replace with an animator.
185 [view setFrame:frame];
186 }
187
188 [browserController_ infoBarResized:[self desiredHeight]];
189 }
190
191 @end
OLDNEW
« 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