| 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 |