OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/ui/views/infobars/infobar_view.h" | 5 #include "chrome/browser/ui/views/infobars/infobar_view.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 | 72 |
73 | 73 |
74 // InfoBarView ---------------------------------------------------------------- | 74 // InfoBarView ---------------------------------------------------------------- |
75 | 75 |
76 // static | 76 // static |
77 const int InfoBarView::kButtonButtonSpacing = views::kRelatedButtonHSpacing; | 77 const int InfoBarView::kButtonButtonSpacing = views::kRelatedButtonHSpacing; |
78 const int InfoBarView::kEndOfLabelSpacing = views::kItemLabelSpacing; | 78 const int InfoBarView::kEndOfLabelSpacing = views::kItemLabelSpacing; |
79 | 79 |
80 InfoBarView::InfoBarView(scoped_ptr<infobars::InfoBarDelegate> delegate) | 80 InfoBarView::InfoBarView(scoped_ptr<infobars::InfoBarDelegate> delegate) |
81 : infobars::InfoBar(std::move(delegate)), | 81 : infobars::InfoBar(std::move(delegate)), |
82 views::ExternalFocusTracker(this, NULL), | 82 views::ExternalFocusTracker(this, nullptr), |
83 icon_(NULL), | 83 child_container_(new views::View()), |
84 close_button_(NULL) { | 84 icon_(nullptr), |
| 85 close_button_(nullptr) { |
85 set_owned_by_client(); // InfoBar deletes itself at the appropriate time. | 86 set_owned_by_client(); // InfoBar deletes itself at the appropriate time. |
86 set_background( | 87 set_background( |
87 new InfoBarBackground(infobars::InfoBar::delegate()->GetInfoBarType())); | 88 new InfoBarBackground(infobars::InfoBar::delegate()->GetInfoBarType())); |
| 89 |
| 90 AddChildView(child_container_); |
| 91 |
| 92 if (ui::MaterialDesignController::IsModeMaterial()) { |
| 93 child_container_->SetPaintToLayer(true); |
| 94 child_container_->layer()->SetMasksToBounds(true); |
| 95 // Since MD doesn't use a gradient, we can set a solid bg color. |
| 96 child_container_->set_background( |
| 97 views::Background::CreateSolidBackground(infobars::InfoBar::GetTopColor( |
| 98 infobars::InfoBar::delegate()->GetInfoBarType()))); |
| 99 } |
88 } | 100 } |
89 | 101 |
90 InfoBarView::~InfoBarView() { | 102 InfoBarView::~InfoBarView() { |
91 // We should have closed any open menus in PlatformSpecificHide(), then | 103 // We should have closed any open menus in PlatformSpecificHide(), then |
92 // subclasses' RunMenu() functions should have prevented opening any new ones | 104 // subclasses' RunMenu() functions should have prevented opening any new ones |
93 // once we became unowned. | 105 // once we became unowned. |
94 DCHECK(!menu_runner_.get()); | 106 DCHECK(!menu_runner_.get()); |
95 } | 107 } |
96 | 108 |
97 views::Label* InfoBarView::CreateLabel(const base::string16& text) const { | 109 views::Label* InfoBarView::CreateLabel(const base::string16& text) const { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 fill_path_.close(); | 213 fill_path_.close(); |
202 } | 214 } |
203 } | 215 } |
204 if (bar_height()) { | 216 if (bar_height()) { |
205 fill_path_.addRect( | 217 fill_path_.addRect( |
206 0.0, SkIntToScalar(arrow_height()), SkIntToScalar(width()), | 218 0.0, SkIntToScalar(arrow_height()), SkIntToScalar(width()), |
207 SkIntToScalar( | 219 SkIntToScalar( |
208 height() - InfoBarContainerDelegate::kSeparatorLineHeight)); | 220 height() - InfoBarContainerDelegate::kSeparatorLineHeight)); |
209 } | 221 } |
210 | 222 |
| 223 child_container_->SetBounds(0, arrow_height(), width(), bar_height()); |
| 224 // |child_container_| should be the only child. |
| 225 DCHECK_EQ(1, child_count()); |
| 226 |
| 227 // Even though other views are technically grandchildren, we'll lay them out |
| 228 // here on behalf of |child_container_|. |
211 int start_x = kEdgeItemPadding; | 229 int start_x = kEdgeItemPadding; |
212 if (icon_ != NULL) { | 230 if (icon_ != NULL) { |
213 icon_->SetPosition(gfx::Point(start_x, OffsetY(icon_))); | 231 icon_->SetPosition(gfx::Point(start_x, OffsetY(icon_))); |
214 start_x = icon_->bounds().right() + kIconToLabelSpacing; | 232 start_x = icon_->bounds().right() + kIconToLabelSpacing; |
215 } | 233 } |
216 | 234 |
217 int content_minimum_width = ContentMinimumWidth(); | 235 int content_minimum_width = ContentMinimumWidth(); |
218 close_button_->SetPosition(gfx::Point( | 236 close_button_->SetPosition(gfx::Point( |
219 std::max( | 237 std::max( |
220 start_x + content_minimum_width + | 238 start_x + content_minimum_width + |
221 ((content_minimum_width > 0) ? kBeforeCloseButtonSpacing : 0), | 239 ((content_minimum_width > 0) ? kBeforeCloseButtonSpacing : 0), |
222 width() - kEdgeItemPadding - close_button_->width()), | 240 width() - kEdgeItemPadding - close_button_->width()), |
223 OffsetY(close_button_))); | 241 OffsetY(close_button_))); |
224 } | 242 } |
225 | 243 |
226 void InfoBarView::ViewHierarchyChanged( | 244 void InfoBarView::ViewHierarchyChanged( |
227 const ViewHierarchyChangedDetails& details) { | 245 const ViewHierarchyChangedDetails& details) { |
228 View::ViewHierarchyChanged(details); | 246 View::ViewHierarchyChanged(details); |
229 | 247 |
230 if (details.is_add && (details.child == this) && (close_button_ == NULL)) { | 248 if (details.is_add && (details.child == this) && (close_button_ == NULL)) { |
231 gfx::Image image = delegate()->GetIcon(); | 249 gfx::Image image = delegate()->GetIcon(); |
232 if (!image.IsEmpty()) { | 250 if (!image.IsEmpty()) { |
233 icon_ = new views::ImageView; | 251 icon_ = new views::ImageView; |
234 icon_->SetImage(image.ToImageSkia()); | 252 icon_->SetImage(image.ToImageSkia()); |
235 icon_->SizeToPreferredSize(); | 253 icon_->SizeToPreferredSize(); |
236 AddChildView(icon_); | 254 child_container_->AddChildView(icon_); |
237 } | 255 } |
238 | 256 |
239 if (ui::MaterialDesignController::IsModeMaterial()) { | 257 if (ui::MaterialDesignController::IsModeMaterial()) { |
240 BarControlButton* close = new BarControlButton(this); | 258 BarControlButton* close = new BarControlButton(this); |
241 close->SetIcon(gfx::VectorIconId::BAR_CLOSE, | 259 close->SetIcon(gfx::VectorIconId::BAR_CLOSE, |
242 base::Bind(&GetInfobarTextColor)); | 260 base::Bind(&GetInfobarTextColor)); |
243 close->set_request_focus_on_press(false); | 261 close->set_request_focus_on_press(false); |
244 close_button_ = close; | 262 close_button_ = close; |
245 } else { | 263 } else { |
246 close_button_ = new views::ImageButton(this); | 264 close_button_ = new views::ImageButton(this); |
247 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 265 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
248 close_button_->SetImage(views::CustomButton::STATE_NORMAL, | 266 close_button_->SetImage(views::CustomButton::STATE_NORMAL, |
249 rb.GetImageNamed(IDR_CLOSE_1).ToImageSkia()); | 267 rb.GetImageNamed(IDR_CLOSE_1).ToImageSkia()); |
250 close_button_->SetImage(views::CustomButton::STATE_HOVERED, | 268 close_button_->SetImage(views::CustomButton::STATE_HOVERED, |
251 rb.GetImageNamed(IDR_CLOSE_1_H).ToImageSkia()); | 269 rb.GetImageNamed(IDR_CLOSE_1_H).ToImageSkia()); |
252 close_button_->SetImage(views::CustomButton::STATE_PRESSED, | 270 close_button_->SetImage(views::CustomButton::STATE_PRESSED, |
253 rb.GetImageNamed(IDR_CLOSE_1_P).ToImageSkia()); | 271 rb.GetImageNamed(IDR_CLOSE_1_P).ToImageSkia()); |
254 } | 272 } |
255 close_button_->SizeToPreferredSize(); | 273 close_button_->SizeToPreferredSize(); |
256 close_button_->SetAccessibleName( | 274 close_button_->SetAccessibleName( |
257 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); | 275 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); |
258 close_button_->SetFocusable(true); | 276 close_button_->SetFocusable(true); |
259 AddChildView(close_button_); | 277 child_container_->AddChildView(close_button_); |
260 } else if ((close_button_ != NULL) && (details.parent == this) && | 278 } else if ((close_button_ != NULL) && (details.parent == this) && |
261 (details.child != close_button_) && (close_button_->parent() == this) && | 279 (details.child != close_button_) && (close_button_->parent() == this) && |
262 (child_at(child_count() - 1) != close_button_)) { | 280 (child_at(child_count() - 1) != close_button_)) { |
263 // For accessibility, ensure the close button is the last child view. | 281 // For accessibility, ensure the close button is the last child view. |
264 RemoveChildView(close_button_); | 282 RemoveChildView(close_button_); |
265 AddChildView(close_button_); | 283 child_container_->AddChildView(close_button_); |
266 } | 284 } |
267 | 285 |
268 // Ensure the infobar is tall enough to display its contents. | 286 // Ensure the infobar is tall enough to display its contents. |
269 int height = ui::MaterialDesignController::IsModeMaterial() | 287 int height = ui::MaterialDesignController::IsModeMaterial() |
270 ? InfoBarContainerDelegate::kDefaultBarTargetHeightMd | 288 ? InfoBarContainerDelegate::kDefaultBarTargetHeightMd |
271 : InfoBarContainerDelegate::kDefaultBarTargetHeight; | 289 : InfoBarContainerDelegate::kDefaultBarTargetHeight; |
272 const int kMinimumVerticalPadding = 6; | 290 const int kMinimumVerticalPadding = 6; |
273 for (int i = 0; i < child_count(); ++i) { | 291 for (int i = 0; i < child_count(); ++i) { |
274 const int child_height = child_at(i)->height(); | 292 const int child_height = child_at(i)->height(); |
275 height = std::max(height, child_height + kMinimumVerticalPadding); | 293 height = std::max(height, child_height + kMinimumVerticalPadding); |
276 } | 294 } |
277 SetBarTargetHeight(height); | 295 SetBarTargetHeight(height); |
278 } | 296 } |
279 | 297 |
280 void InfoBarView::PaintChildren(const ui::PaintContext& context) { | |
281 // TODO(scr): This really should be the |fill_path_|, but the clipPath seems | |
282 // broken on non-Windows platforms (crbug.com/75154). For now, just clip to | |
283 // the bar bounds. | |
284 // | |
285 // canvas->sk_canvas()->clipPath(fill_path_); | |
286 DCHECK_EQ(total_height(), height()) | |
287 << "Infobar piecewise heights do not match overall height"; | |
288 ui::ClipRecorder clip_recorder(context); | |
289 clip_recorder.ClipRect(gfx::Rect(0, arrow_height(), width(), bar_height())); | |
290 views::View::PaintChildren(context); | |
291 } | |
292 | |
293 void InfoBarView::ButtonPressed(views::Button* sender, | 298 void InfoBarView::ButtonPressed(views::Button* sender, |
294 const ui::Event& event) { | 299 const ui::Event& event) { |
295 if (!owner()) | 300 if (!owner()) |
296 return; // We're closing; don't call anything, it might access the owner. | 301 return; // We're closing; don't call anything, it might access the owner. |
297 if (sender == close_button_) { | 302 if (sender == close_button_) { |
298 delegate()->InfoBarDismissed(); | 303 delegate()->InfoBarDismissed(); |
299 RemoveSelf(); | 304 RemoveSelf(); |
300 } | 305 } |
301 } | 306 } |
302 | 307 |
303 int InfoBarView::ContentMinimumWidth() const { | 308 int InfoBarView::ContentMinimumWidth() const { |
304 return 0; | 309 return 0; |
305 } | 310 } |
306 | 311 |
307 int InfoBarView::StartX() const { | 312 int InfoBarView::StartX() const { |
308 // Ensure we don't return a value greater than EndX(), so children can safely | 313 // Ensure we don't return a value greater than EndX(), so children can safely |
309 // set something's width to "EndX() - StartX()" without risking that being | 314 // set something's width to "EndX() - StartX()" without risking that being |
310 // negative. | 315 // negative. |
311 return std::min(EndX(), (icon_ != NULL) ? | 316 return std::min(EndX(), (icon_ != NULL) ? |
312 (icon_->bounds().right() + kIconToLabelSpacing) : kEdgeItemPadding); | 317 (icon_->bounds().right() + kIconToLabelSpacing) : kEdgeItemPadding); |
313 } | 318 } |
314 | 319 |
315 int InfoBarView::EndX() const { | 320 int InfoBarView::EndX() const { |
316 return close_button_->x() - kBeforeCloseButtonSpacing; | 321 return close_button_->x() - kBeforeCloseButtonSpacing; |
317 } | 322 } |
318 | 323 |
319 int InfoBarView::OffsetY(views::View* view) const { | 324 int InfoBarView::OffsetY(views::View* view) const { |
320 return arrow_height() + | 325 return std::max((bar_target_height() - view->height()) / 2, 0) - |
321 std::max((bar_target_height() - view->height()) / 2, 0) - | 326 (bar_target_height() - bar_height()); |
322 (bar_target_height() - bar_height()); | |
323 } | 327 } |
324 | 328 |
325 const infobars::InfoBarContainer::Delegate* InfoBarView::container_delegate() | 329 const infobars::InfoBarContainer::Delegate* InfoBarView::container_delegate() |
326 const { | 330 const { |
327 const infobars::InfoBarContainer* infobar_container = container(); | 331 const infobars::InfoBarContainer* infobar_container = container(); |
328 return infobar_container ? infobar_container->delegate() : NULL; | 332 return infobar_container ? infobar_container->delegate() : NULL; |
329 } | 333 } |
330 | 334 |
331 void InfoBarView::RunMenuAt(ui::MenuModel* menu_model, | 335 void InfoBarView::RunMenuAt(ui::MenuModel* menu_model, |
332 views::MenuButton* button, | 336 views::MenuButton* button, |
333 views::MenuAnchorPosition anchor) { | 337 views::MenuAnchorPosition anchor) { |
334 DCHECK(owner()); // We'd better not open any menus while we're closing. | 338 DCHECK(owner()); // We'd better not open any menus while we're closing. |
335 gfx::Point screen_point; | 339 gfx::Point screen_point; |
336 views::View::ConvertPointToScreen(button, &screen_point); | 340 views::View::ConvertPointToScreen(button, &screen_point); |
337 menu_runner_.reset( | 341 menu_runner_.reset( |
338 new views::MenuRunner(menu_model, views::MenuRunner::HAS_MNEMONICS)); | 342 new views::MenuRunner(menu_model, views::MenuRunner::HAS_MNEMONICS)); |
339 // Ignore the result since we don't need to handle a deleted menu specially. | 343 // Ignore the result since we don't need to handle a deleted menu specially. |
340 ignore_result(menu_runner_->RunMenuAt(GetWidget(), | 344 ignore_result(menu_runner_->RunMenuAt(GetWidget(), |
341 button, | 345 button, |
342 gfx::Rect(screen_point, button->size()), | 346 gfx::Rect(screen_point, button->size()), |
343 anchor, | 347 anchor, |
344 ui::MENU_SOURCE_NONE)); | 348 ui::MENU_SOURCE_NONE)); |
345 } | 349 } |
346 | 350 |
| 351 void InfoBarView::AddViewToContentArea(views::View* view) { |
| 352 child_container_->AddChildView(view); |
| 353 } |
| 354 |
347 // static | 355 // static |
348 void InfoBarView::AssignWidthsSorted(Labels* labels, int available_width) { | 356 void InfoBarView::AssignWidthsSorted(Labels* labels, int available_width) { |
349 if (labels->empty()) | 357 if (labels->empty()) |
350 return; | 358 return; |
351 gfx::Size back_label_size(labels->back()->GetPreferredSize()); | 359 gfx::Size back_label_size(labels->back()->GetPreferredSize()); |
352 back_label_size.set_width( | 360 back_label_size.set_width( |
353 std::min(back_label_size.width(), | 361 std::min(back_label_size.width(), |
354 available_width / static_cast<int>(labels->size()))); | 362 available_width / static_cast<int>(labels->size()))); |
355 labels->back()->SetSize(back_label_size); | 363 labels->back()->SetSize(back_label_size); |
356 labels->pop_back(); | 364 labels->pop_back(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 void InfoBarView::OnWillChangeFocus(View* focused_before, View* focused_now) { | 421 void InfoBarView::OnWillChangeFocus(View* focused_before, View* focused_now) { |
414 views::ExternalFocusTracker::OnWillChangeFocus(focused_before, focused_now); | 422 views::ExternalFocusTracker::OnWillChangeFocus(focused_before, focused_now); |
415 | 423 |
416 // This will trigger some screen readers to read the entire contents of this | 424 // This will trigger some screen readers to read the entire contents of this |
417 // infobar. | 425 // infobar. |
418 if (focused_before && focused_now && !Contains(focused_before) && | 426 if (focused_before && focused_now && !Contains(focused_before) && |
419 Contains(focused_now)) { | 427 Contains(focused_now)) { |
420 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true); | 428 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true); |
421 } | 429 } |
422 } | 430 } |
OLD | NEW |