OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/logging.h" | 5 #include "base/logging.h" |
6 #include "base/mac_util.h" | 6 #include "base/mac_util.h" |
| 7 #import "chrome/browser/cocoa/animatable_view.h" |
7 #include "chrome/browser/cocoa/infobar.h" | 8 #include "chrome/browser/cocoa/infobar.h" |
8 #import "chrome/browser/cocoa/infobar_container_controller.h" | 9 #import "chrome/browser/cocoa/infobar_container_controller.h" |
9 #import "chrome/browser/cocoa/infobar_controller.h" | 10 #import "chrome/browser/cocoa/infobar_controller.h" |
10 #include "chrome/browser/cocoa/tab_strip_model_observer_bridge.h" | 11 #include "chrome/browser/cocoa/tab_strip_model_observer_bridge.h" |
11 #include "chrome/browser/tab_contents/tab_contents.h" | 12 #include "chrome/browser/tab_contents/tab_contents.h" |
12 #include "chrome/common/notification_service.h" | 13 #include "chrome/common/notification_service.h" |
13 #include "skia/ext/skia_utils_mac.h" | 14 #include "skia/ext/skia_utils_mac.h" |
14 | 15 |
15 // C++ class that receives INFOBAR_ADDED and INFOBAR_REMOVED | 16 // C++ class that receives INFOBAR_ADDED and INFOBAR_REMOVED |
16 // notifications and proxies them back to |controller|. | 17 // notifications and proxies them back to |controller|. |
17 class InfoBarNotificationObserver : public NotificationObserver { | 18 class InfoBarNotificationObserver : public NotificationObserver { |
18 public: | 19 public: |
19 InfoBarNotificationObserver(InfoBarContainerController* controller) | 20 InfoBarNotificationObserver(InfoBarContainerController* controller) |
20 : controller_(controller) { | 21 : controller_(controller) { |
21 } | 22 } |
22 | 23 |
23 private: | 24 private: |
24 // NotificationObserver implementation | 25 // NotificationObserver implementation |
25 void Observe(NotificationType type, | 26 void Observe(NotificationType type, |
26 const NotificationSource& source, | 27 const NotificationSource& source, |
27 const NotificationDetails& details) { | 28 const NotificationDetails& details) { |
28 switch (type.value) { | 29 switch (type.value) { |
29 case NotificationType::TAB_CONTENTS_INFOBAR_ADDED: | 30 case NotificationType::TAB_CONTENTS_INFOBAR_ADDED: |
30 [controller_ addInfoBar:Details<InfoBarDelegate>(details).ptr()]; | 31 [controller_ addInfoBar:Details<InfoBarDelegate>(details).ptr() |
| 32 animate:YES]; |
31 break; | 33 break; |
32 case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED: | 34 case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED: |
33 [controller_ | 35 [controller_ |
34 removeInfoBarsForDelegate:Details<InfoBarDelegate>(details).ptr()]; | 36 closeInfoBarsForDelegate:Details<InfoBarDelegate>(details).ptr() |
| 37 animate:YES]; |
35 break; | 38 break; |
36 case NotificationType::TAB_CONTENTS_INFOBAR_REPLACED: { | 39 case NotificationType::TAB_CONTENTS_INFOBAR_REPLACED: { |
37 typedef std::pair<InfoBarDelegate*, InfoBarDelegate*> | 40 typedef std::pair<InfoBarDelegate*, InfoBarDelegate*> |
38 InfoBarDelegatePair; | 41 InfoBarDelegatePair; |
39 InfoBarDelegatePair* delegates = | 42 InfoBarDelegatePair* delegates = |
40 Details<InfoBarDelegatePair>(details).ptr(); | 43 Details<InfoBarDelegatePair>(details).ptr(); |
41 [controller_ | 44 [controller_ |
42 replaceInfoBarsForDelegate:delegates->first with:delegates->second]; | 45 replaceInfoBarsForDelegate:delegates->first with:delegates->second]; |
43 break; | 46 break; |
44 } | 47 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 - (void)dealloc { | 93 - (void)dealloc { |
91 DCHECK([infobarControllers_ count] == 0); | 94 DCHECK([infobarControllers_ count] == 0); |
92 [super dealloc]; | 95 [super dealloc]; |
93 } | 96 } |
94 | 97 |
95 - (void)removeDelegate:(InfoBarDelegate*)delegate { | 98 - (void)removeDelegate:(InfoBarDelegate*)delegate { |
96 DCHECK(currentTabContents_); | 99 DCHECK(currentTabContents_); |
97 currentTabContents_->RemoveInfoBar(delegate); | 100 currentTabContents_->RemoveInfoBar(delegate); |
98 } | 101 } |
99 | 102 |
| 103 - (void)removeController:(InfoBarController*)controller { |
| 104 // This code can be executed while InfoBarController is still on the stack, so |
| 105 // we retain and autorelease the controller to prevent it from being |
| 106 // dealloc'ed too early. |
| 107 [[controller retain] autorelease]; |
| 108 [[controller view] removeFromSuperview]; |
| 109 [infobarControllers_ removeObject:controller]; |
| 110 [self positionInfoBarsAndRedraw]; |
| 111 } |
| 112 |
100 // TabStripModelObserverBridge notifications | 113 // TabStripModelObserverBridge notifications |
101 - (void)selectTabWithContents:(TabContents*)newContents | 114 - (void)selectTabWithContents:(TabContents*)newContents |
102 previousContents:(TabContents*)oldContents | 115 previousContents:(TabContents*)oldContents |
103 atIndex:(NSInteger)index | 116 atIndex:(NSInteger)index |
104 userGesture:(bool)wasUserGesture { | 117 userGesture:(bool)wasUserGesture { |
105 [self changeTabContents:newContents]; | 118 [self changeTabContents:newContents]; |
106 } | 119 } |
107 | 120 |
108 - (void)tabDetachedWithContents:(TabContents*)contents | 121 - (void)tabDetachedWithContents:(TabContents*)contents |
109 atIndex:(NSInteger)index { | 122 atIndex:(NSInteger)index { |
110 [self changeTabContents:NULL]; | 123 [self changeTabContents:NULL]; |
111 } | 124 } |
112 | 125 |
| 126 - (void)resizeView:(NSView*)view newHeight:(float)height { |
| 127 NSRect frame = [view frame]; |
| 128 frame.size.height = height; |
| 129 [view setFrame:frame]; |
| 130 [self positionInfoBarsAndRedraw]; |
| 131 } |
| 132 |
113 @end | 133 @end |
114 | 134 |
115 @implementation InfoBarContainerController (PrivateMethods) | 135 @implementation InfoBarContainerController (PrivateMethods) |
116 | 136 |
117 - (float)desiredHeight { | 137 - (float)desiredHeight { |
118 float height = 0; | 138 float height = 0; |
119 | 139 |
120 for (InfoBarController* controller in infobarControllers_.get()) { | 140 for (InfoBarController* controller in infobarControllers_.get()) { |
121 height += [[controller view] frame].size.height; | 141 height += [[controller view] frame].size.height; |
122 } | 142 } |
123 | 143 |
124 return height; | 144 return height; |
125 } | 145 } |
126 | 146 |
127 - (void)changeTabContents:(TabContents*)contents { | 147 - (void)changeTabContents:(TabContents*)contents { |
128 registrar_.RemoveAll(); | 148 registrar_.RemoveAll(); |
129 [self removeAllInfoBars]; | 149 [self removeAllInfoBars]; |
130 | 150 |
131 currentTabContents_ = contents; | 151 currentTabContents_ = contents; |
132 if (currentTabContents_) { | 152 if (currentTabContents_) { |
133 for (int i = 0; i < currentTabContents_->infobar_delegate_count(); ++i) { | 153 for (int i = 0; i < currentTabContents_->infobar_delegate_count(); ++i) { |
134 [self addInfoBar:currentTabContents_->GetInfoBarDelegateAt(i)]; | 154 [self addInfoBar:currentTabContents_->GetInfoBarDelegateAt(i) |
| 155 animate:NO]; |
135 } | 156 } |
136 | 157 |
137 Source<TabContents> source(currentTabContents_); | 158 Source<TabContents> source(currentTabContents_); |
138 registrar_.Add(infoBarObserver_.get(), | 159 registrar_.Add(infoBarObserver_.get(), |
139 NotificationType::TAB_CONTENTS_INFOBAR_ADDED, source); | 160 NotificationType::TAB_CONTENTS_INFOBAR_ADDED, source); |
140 registrar_.Add(infoBarObserver_.get(), | 161 registrar_.Add(infoBarObserver_.get(), |
141 NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, source); | 162 NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, source); |
142 registrar_.Add(infoBarObserver_.get(), | 163 registrar_.Add(infoBarObserver_.get(), |
143 NotificationType::TAB_CONTENTS_INFOBAR_REPLACED, source); | 164 NotificationType::TAB_CONTENTS_INFOBAR_REPLACED, source); |
144 } | 165 } |
145 | 166 |
146 [self positionInfoBarsAndRedraw]; | 167 [self positionInfoBarsAndRedraw]; |
147 } | 168 } |
148 | 169 |
149 - (void)addInfoBar:(InfoBarDelegate*)delegate { | 170 - (void)addInfoBar:(InfoBarDelegate*)delegate animate:(BOOL)animate { |
150 scoped_ptr<InfoBar> infobar(delegate->CreateInfoBar()); | 171 scoped_ptr<InfoBar> infobar(delegate->CreateInfoBar()); |
151 InfoBarController* controller = infobar->controller(); | 172 InfoBarController* controller = infobar->controller(); |
152 [controller setContainerController:self]; | 173 [controller setContainerController:self]; |
| 174 [[controller animatableView] setResizeDelegate:self]; |
153 [[self view] addSubview:[controller view]]; | 175 [[self view] addSubview:[controller view]]; |
154 [infobarControllers_ addObject:[controller autorelease]]; | 176 [infobarControllers_ addObject:[controller autorelease]]; |
| 177 |
| 178 if (animate) |
| 179 [controller animateOpen]; |
| 180 else |
| 181 [controller open]; |
155 } | 182 } |
156 | 183 |
157 - (void)removeInfoBarsForDelegate:(InfoBarDelegate*)delegate { | 184 - (void)closeInfoBarsForDelegate:(InfoBarDelegate*)delegate |
| 185 animate:(BOOL)animate { |
158 for (InfoBarController* controller in | 186 for (InfoBarController* controller in |
159 [NSArray arrayWithArray:infobarControllers_.get()]) { | 187 [NSArray arrayWithArray:infobarControllers_.get()]) { |
160 if ([controller delegate] == delegate) { | 188 if ([controller delegate] == delegate) { |
161 // This code can be executed while -[InfoBarController closeInfoBar] is | 189 if (animate) |
162 // still on the stack, so we retain and autorelease the controller to | 190 [controller animateClosed]; |
163 // prevent it from being dealloc'ed too early. | 191 else |
164 [[controller retain] autorelease]; | 192 [controller close]; |
165 [[controller view] removeFromSuperview]; | |
166 [infobarControllers_ removeObject:controller]; | |
167 } | 193 } |
168 } | 194 } |
169 } | 195 } |
170 | 196 |
171 - (void)replaceInfoBarsForDelegate:(InfoBarDelegate*)old_delegate | 197 - (void)replaceInfoBarsForDelegate:(InfoBarDelegate*)old_delegate |
172 with:(InfoBarDelegate*)new_delegate { | 198 with:(InfoBarDelegate*)new_delegate { |
173 // TODO(rohitrao): This should avoid animation when we add it. | 199 [self closeInfoBarsForDelegate:old_delegate animate:NO]; |
174 [self removeInfoBarsForDelegate:old_delegate]; | 200 [self addInfoBar:new_delegate animate:NO]; |
175 [self addInfoBar:new_delegate]; | |
176 } | 201 } |
177 | 202 |
178 - (void)removeAllInfoBars { | 203 - (void)removeAllInfoBars { |
179 for (InfoBarController* controller in infobarControllers_.get()) { | 204 for (InfoBarController* controller in infobarControllers_.get()) { |
| 205 [[controller animatableView] stopAnimation]; |
180 [[controller view] removeFromSuperview]; | 206 [[controller view] removeFromSuperview]; |
181 } | 207 } |
182 [infobarControllers_ removeAllObjects]; | 208 [infobarControllers_ removeAllObjects]; |
183 } | 209 } |
184 | 210 |
185 - (void)positionInfoBarsAndRedraw { | 211 - (void)positionInfoBarsAndRedraw { |
186 NSRect containerBounds = [[self view] bounds]; | 212 NSRect containerBounds = [[self view] bounds]; |
187 int minY = 0; | 213 int minY = 0; |
188 | 214 |
189 // Stack the infobars at the bottom of the view, starting with the | 215 // Stack the infobars at the bottom of the view, starting with the |
190 // last infobar and working our way to the front of the array. This | 216 // last infobar and working our way to the front of the array. This |
191 // way we ensure that the first infobar added shows up on top, with | 217 // way we ensure that the first infobar added shows up on top, with |
192 // the others below. | 218 // the others below. |
193 for (InfoBarController* controller in | 219 for (InfoBarController* controller in |
194 [infobarControllers_ reverseObjectEnumerator]) { | 220 [infobarControllers_ reverseObjectEnumerator]) { |
195 NSView* view = [controller view]; | 221 NSView* view = [controller view]; |
196 NSRect frame = [view frame]; | 222 NSRect frame = [view frame]; |
197 frame.origin.x = NSMinX(containerBounds); | 223 frame.origin.x = NSMinX(containerBounds); |
198 frame.size.width = NSWidth(containerBounds); | 224 frame.size.width = NSWidth(containerBounds); |
199 frame.origin.y = minY; | 225 frame.origin.y = minY; |
200 minY += frame.size.height; | 226 minY += frame.size.height; |
201 // TODO(rohitrao, jrg): Replace with an animator. | |
202 [view setFrame:frame]; | 227 [view setFrame:frame]; |
203 } | 228 } |
204 | 229 |
205 [resizeDelegate_ resizeView:[self view] newHeight:[self desiredHeight]]; | 230 [resizeDelegate_ resizeView:[self view] newHeight:[self desiredHeight]]; |
206 } | 231 } |
207 | 232 |
208 @end | 233 @end |
OLD | NEW |