Chromium Code Reviews| 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 <memory> | 8 #include <memory> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "chrome/browser/ui/infobar_container_delegate.h" | 13 #include "chrome/browser/ui/infobar_container_delegate.h" |
| 14 #include "chrome/browser/ui/views/infobars/infobar_background.h" | 14 #include "chrome/browser/ui/views/infobars/infobar_background.h" |
| 15 #include "chrome/grit/generated_resources.h" | 15 #include "chrome/grit/generated_resources.h" |
| 16 #include "chrome/grit/theme_resources.h" | 16 #include "chrome/grit/theme_resources.h" |
| 17 #include "components/infobars/core/infobar_delegate.h" | 17 #include "components/infobars/core/infobar_delegate.h" |
| 18 #include "components/strings/grit/components_strings.h" | 18 #include "components/strings/grit/components_strings.h" |
| 19 #include "third_party/skia/include/effects/SkGradientShader.h" | 19 #include "third_party/skia/include/effects/SkGradientShader.h" |
| 20 #include "ui/accessibility/ax_view_state.h" | 20 #include "ui/accessibility/ax_view_state.h" |
| 21 #include "ui/base/l10n/l10n_util.h" | 21 #include "ui/base/l10n/l10n_util.h" |
| 22 #include "ui/base/material_design/material_design_controller.h" | |
| 23 #include "ui/base/resource/resource_bundle.h" | 22 #include "ui/base/resource/resource_bundle.h" |
| 24 #include "ui/gfx/canvas.h" | 23 #include "ui/gfx/canvas.h" |
| 25 #include "ui/gfx/color_palette.h" | 24 #include "ui/gfx/color_palette.h" |
| 26 #include "ui/gfx/image/image.h" | 25 #include "ui/gfx/image/image.h" |
| 27 #include "ui/gfx/paint_vector_icon.h" | 26 #include "ui/gfx/paint_vector_icon.h" |
| 28 #include "ui/gfx/vector_icons_public.h" | 27 #include "ui/gfx/vector_icons_public.h" |
| 29 #include "ui/native_theme/common_theme.h" | 28 #include "ui/native_theme/common_theme.h" |
| 30 #include "ui/native_theme/native_theme.h" | 29 #include "ui/native_theme/native_theme.h" |
| 31 #include "ui/resources/grit/ui_resources.h" | 30 #include "ui/resources/grit/ui_resources.h" |
| 32 #include "ui/views/controls/button/image_button.h" | 31 #include "ui/views/controls/button/image_button.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 50 | 49 |
| 51 const int kEdgeItemPadding = views::kRelatedControlHorizontalSpacing; | 50 const int kEdgeItemPadding = views::kRelatedControlHorizontalSpacing; |
| 52 const int kIconToLabelSpacing = views::kRelatedControlHorizontalSpacing; | 51 const int kIconToLabelSpacing = views::kRelatedControlHorizontalSpacing; |
| 53 const int kBeforeCloseButtonSpacing = views::kUnrelatedControlHorizontalSpacing; | 52 const int kBeforeCloseButtonSpacing = views::kUnrelatedControlHorizontalSpacing; |
| 54 | 53 |
| 55 bool SortLabelsByDecreasingWidth(views::Label* label_1, views::Label* label_2) { | 54 bool SortLabelsByDecreasingWidth(views::Label* label_1, views::Label* label_2) { |
| 56 return label_1->GetPreferredSize().width() > | 55 return label_1->GetPreferredSize().width() > |
| 57 label_2->GetPreferredSize().width(); | 56 label_2->GetPreferredSize().width(); |
| 58 } | 57 } |
| 59 | 58 |
| 60 const gfx::FontList& GetFontList() { | |
| 61 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 62 return rb.GetFontList(ui::MaterialDesignController::IsModeMaterial() | |
| 63 ? ui::ResourceBundle::BaseFont | |
| 64 : ui::ResourceBundle::MediumFont); | |
| 65 } | |
| 66 | |
| 67 constexpr SkColor GetInfobarTextColor() { | 59 constexpr SkColor GetInfobarTextColor() { |
| 68 return SK_ColorBLACK; | 60 return SK_ColorBLACK; |
| 69 } | 61 } |
| 70 | 62 |
| 71 } // namespace | 63 } // namespace |
| 72 | 64 |
| 73 | 65 |
| 74 // InfoBarView ---------------------------------------------------------------- | 66 // InfoBarView ---------------------------------------------------------------- |
| 75 | 67 |
| 76 // static | 68 // static |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 87 set_owned_by_client(); // InfoBar deletes itself at the appropriate time. | 79 set_owned_by_client(); // InfoBar deletes itself at the appropriate time. |
| 88 set_background( | 80 set_background( |
| 89 new InfoBarBackground(infobars::InfoBar::delegate()->GetInfoBarType())); | 81 new InfoBarBackground(infobars::InfoBar::delegate()->GetInfoBarType())); |
| 90 SetEventTargeter(base::MakeUnique<views::ViewTargeter>(this)); | 82 SetEventTargeter(base::MakeUnique<views::ViewTargeter>(this)); |
| 91 | 83 |
| 92 AddChildView(child_container_); | 84 AddChildView(child_container_); |
| 93 | 85 |
| 94 SetPaintToLayer(true); | 86 SetPaintToLayer(true); |
| 95 layer()->SetFillsBoundsOpaquely(false); | 87 layer()->SetFillsBoundsOpaquely(false); |
| 96 | 88 |
| 97 if (ui::MaterialDesignController::IsModeMaterial()) { | 89 child_container_->SetPaintToLayer(true); |
| 98 child_container_->SetPaintToLayer(true); | 90 child_container_->layer()->SetMasksToBounds(true); |
| 99 child_container_->layer()->SetMasksToBounds(true); | 91 child_container_->set_background( |
| 100 // Since MD doesn't use a gradient, we can set a solid bg color. | 92 views::Background::CreateSolidBackground(infobars::InfoBar::GetTopColor( |
| 101 child_container_->set_background( | 93 infobars::InfoBar::delegate()->GetInfoBarType()))); |
| 102 views::Background::CreateSolidBackground(infobars::InfoBar::GetTopColor( | |
| 103 infobars::InfoBar::delegate()->GetInfoBarType()))); | |
| 104 } | |
| 105 } | 94 } |
| 106 | 95 |
| 107 const infobars::InfoBarContainer::Delegate* InfoBarView::container_delegate() | 96 const infobars::InfoBarContainer::Delegate* InfoBarView::container_delegate() |
| 108 const { | 97 const { |
| 109 const infobars::InfoBarContainer* infobar_container = container(); | 98 const infobars::InfoBarContainer* infobar_container = container(); |
| 110 return infobar_container ? infobar_container->delegate() : NULL; | 99 return infobar_container ? infobar_container->delegate() : NULL; |
| 111 } | 100 } |
| 112 | 101 |
| 113 InfoBarView::~InfoBarView() { | 102 InfoBarView::~InfoBarView() { |
| 114 // We should have closed any open menus in PlatformSpecificHide(), then | 103 // We should have closed any open menus in PlatformSpecificHide(), then |
| 115 // subclasses' RunMenu() functions should have prevented opening any new ones | 104 // subclasses' RunMenu() functions should have prevented opening any new ones |
| 116 // once we became unowned. | 105 // once we became unowned. |
| 117 DCHECK(!menu_runner_.get()); | 106 DCHECK(!menu_runner_.get()); |
| 118 } | 107 } |
| 119 | 108 |
| 120 views::Label* InfoBarView::CreateLabel(const base::string16& text) const { | 109 views::Label* InfoBarView::CreateLabel(const base::string16& text) const { |
| 121 views::Label* label = new views::Label(text, GetFontList()); | 110 views::Label* label = new views::Label(text); |
| 122 label->SizeToPreferredSize(); | 111 label->SizeToPreferredSize(); |
| 123 label->SetBackgroundColor(background()->get_color()); | 112 label->SetBackgroundColor(background()->get_color()); |
| 124 label->SetEnabledColor(GetInfobarTextColor()); | 113 label->SetEnabledColor(GetInfobarTextColor()); |
| 125 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 114 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 126 return label; | 115 return label; |
| 127 } | 116 } |
| 128 | 117 |
| 129 views::Link* InfoBarView::CreateLink(const base::string16& text, | 118 views::Link* InfoBarView::CreateLink(const base::string16& text, |
| 130 views::LinkListener* listener) const { | 119 views::LinkListener* listener) const { |
| 131 views::Link* link = new views::Link(text); | 120 views::Link* link = new views::Link(text); |
| 132 link->SetFontList(GetFontList()); | |
| 133 link->SizeToPreferredSize(); | 121 link->SizeToPreferredSize(); |
| 134 link->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 122 link->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 135 link->set_listener(listener); | 123 link->set_listener(listener); |
| 136 link->SetBackgroundColor(background()->get_color()); | 124 link->SetBackgroundColor(background()->get_color()); |
| 137 return link; | 125 return link; |
| 138 } | 126 } |
| 139 | 127 |
| 140 // static | 128 // static |
| 141 views::LabelButton* InfoBarView::CreateTextButton( | |
| 142 views::ButtonListener* listener, | |
| 143 const base::string16& text) { | |
| 144 DCHECK(!ui::MaterialDesignController::IsModeMaterial()); | |
| 145 views::LabelButton* button = new views::LabelButton(listener, text); | |
|
Peter Kasting
2016/09/19 19:04:06
Can we now kill the label_button.h #include?
Any
Evan Stade
2016/09/19 20:06:02
removed a few
| |
| 146 std::unique_ptr<views::LabelButtonAssetBorder> button_border( | |
| 147 new views::LabelButtonAssetBorder(views::Button::STYLE_TEXTBUTTON)); | |
| 148 const int kNormalImageSet[] = IMAGE_GRID(IDR_INFOBARBUTTON_NORMAL); | |
| 149 button_border->SetPainter( | |
| 150 false, views::Button::STATE_NORMAL, | |
| 151 views::Painter::CreateImageGridPainter(kNormalImageSet)); | |
| 152 const int kHoveredImageSet[] = IMAGE_GRID(IDR_INFOBARBUTTON_HOVER); | |
| 153 button_border->SetPainter( | |
| 154 false, views::Button::STATE_HOVERED, | |
| 155 views::Painter::CreateImageGridPainter(kHoveredImageSet)); | |
| 156 const int kPressedImageSet[] = IMAGE_GRID(IDR_INFOBARBUTTON_PRESSED); | |
| 157 button_border->SetPainter( | |
| 158 false, views::Button::STATE_PRESSED, | |
| 159 views::Painter::CreateImageGridPainter(kPressedImageSet)); | |
| 160 button->SetBorder(std::move(button_border)); | |
| 161 button->set_animate_on_state_change(false); | |
| 162 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 163 button->SetFontList(rb.GetFontList(ui::ResourceBundle::MediumFont)); | |
| 164 button->SetFocusForPlatform(); | |
| 165 button->set_request_focus_on_press(true); | |
| 166 button->SetTextColor(views::Button::STATE_NORMAL, GetInfobarTextColor()); | |
| 167 button->SetTextColor(views::Button::STATE_HOVERED, GetInfobarTextColor()); | |
| 168 return button; | |
| 169 } | |
| 170 | |
| 171 // static | |
| 172 void InfoBarView::AssignWidths(Labels* labels, int available_width) { | 129 void InfoBarView::AssignWidths(Labels* labels, int available_width) { |
| 173 std::sort(labels->begin(), labels->end(), SortLabelsByDecreasingWidth); | 130 std::sort(labels->begin(), labels->end(), SortLabelsByDecreasingWidth); |
| 174 AssignWidthsSorted(labels, available_width); | 131 AssignWidthsSorted(labels, available_width); |
| 175 } | 132 } |
| 176 | 133 |
| 177 void InfoBarView::Layout() { | 134 void InfoBarView::Layout() { |
| 178 // Calculate the fill and stroke paths. We do this here, rather than in | |
| 179 // PlatformSpecificRecalculateHeight(), because this is also reached when our | |
| 180 // width is changed, which affects both paths. | |
| 181 // TODO(estade): these paths aren't used for MD; remove when MD is default. | |
| 182 stroke_path_.rewind(); | |
| 183 fill_path_.rewind(); | |
| 184 const infobars::InfoBarContainer::Delegate* delegate = container_delegate(); | |
| 185 if (delegate) { | |
| 186 int arrow_x; | |
| 187 SkScalar arrow_fill_height = SkIntToScalar(std::max( | |
| 188 arrow_height() - InfoBarContainerDelegate::kSeparatorLineHeight, 0)); | |
| 189 SkScalar arrow_fill_half_width = SkIntToScalar(arrow_half_width()); | |
| 190 SkScalar separator_height = | |
| 191 SkIntToScalar(InfoBarContainerDelegate::kSeparatorLineHeight); | |
| 192 if (delegate->DrawInfoBarArrows(&arrow_x) && arrow_fill_height) { | |
| 193 // Skia pixel centers are at the half-values, so the arrow is horizontally | |
| 194 // centered at |arrow_x| + 0.5. Vertically, the stroke path is the center | |
| 195 // of the separator, while the fill path is a closed path that extends up | |
| 196 // through the entire height of the separator and down to the bottom of | |
| 197 // the arrow where it joins the bar. | |
| 198 stroke_path_.moveTo( | |
| 199 SkIntToScalar(arrow_x) + SK_ScalarHalf - arrow_fill_half_width, | |
| 200 SkIntToScalar(arrow_height()) - (separator_height * SK_ScalarHalf)); | |
| 201 stroke_path_.rLineTo(arrow_fill_half_width, -arrow_fill_height); | |
| 202 stroke_path_.rLineTo(arrow_fill_half_width, arrow_fill_height); | |
| 203 | |
| 204 fill_path_ = stroke_path_; | |
| 205 // Move the top of the fill path up to the top of the separator and then | |
| 206 // extend it down all the way through. | |
| 207 fill_path_.offset(0, -separator_height * SK_ScalarHalf); | |
| 208 // This 0.01 hack prevents the fill from filling more pixels on the right | |
| 209 // edge of the arrow than on the left. | |
| 210 const SkScalar epsilon = 0.01f; | |
| 211 fill_path_.rLineTo(-epsilon, 0); | |
| 212 fill_path_.rLineTo(0, separator_height); | |
| 213 fill_path_.rLineTo(epsilon - (arrow_fill_half_width * 2), 0); | |
| 214 fill_path_.close(); | |
| 215 } | |
| 216 } | |
| 217 if (bar_height()) { | |
| 218 fill_path_.addRect( | |
| 219 0.0, SkIntToScalar(arrow_height()), SkIntToScalar(width()), | |
| 220 SkIntToScalar( | |
| 221 height() - InfoBarContainerDelegate::kSeparatorLineHeight)); | |
| 222 } | |
| 223 | |
| 224 child_container_->SetBounds( | 135 child_container_->SetBounds( |
| 225 0, arrow_height(), width(), | 136 0, arrow_height(), width(), |
| 226 bar_height() - InfoBarContainerDelegate::kSeparatorLineHeight); | 137 bar_height() - InfoBarContainerDelegate::kSeparatorLineHeight); |
| 227 // |child_container_| should be the only child. | 138 // |child_container_| should be the only child. |
| 228 DCHECK_EQ(1, child_count()); | 139 DCHECK_EQ(1, child_count()); |
| 229 | 140 |
| 230 // Even though other views are technically grandchildren, we'll lay them out | 141 // Even though other views are technically grandchildren, we'll lay them out |
| 231 // here on behalf of |child_container_|. | 142 // here on behalf of |child_container_|. |
| 232 int start_x = kEdgeItemPadding; | 143 int start_x = kEdgeItemPadding; |
| 233 if (icon_ != NULL) { | 144 if (icon_ != NULL) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 255 | 166 |
| 256 if (details.is_add && (details.child == this) && (close_button_ == NULL)) { | 167 if (details.is_add && (details.child == this) && (close_button_ == NULL)) { |
| 257 gfx::Image image = delegate()->GetIcon(); | 168 gfx::Image image = delegate()->GetIcon(); |
| 258 if (!image.IsEmpty()) { | 169 if (!image.IsEmpty()) { |
| 259 icon_ = new views::ImageView; | 170 icon_ = new views::ImageView; |
| 260 icon_->SetImage(image.ToImageSkia()); | 171 icon_->SetImage(image.ToImageSkia()); |
| 261 icon_->SizeToPreferredSize(); | 172 icon_->SizeToPreferredSize(); |
| 262 child_container_->AddChildView(icon_); | 173 child_container_->AddChildView(icon_); |
| 263 } | 174 } |
| 264 | 175 |
| 265 if (ui::MaterialDesignController::IsModeMaterial()) { | 176 close_button_ = new views::VectorIconButton(this); |
| 266 views::VectorIconButton* close = new views::VectorIconButton(this); | 177 close_button_->SetIcon(gfx::VectorIconId::BAR_CLOSE); |
| 267 close->SetIcon(gfx::VectorIconId::BAR_CLOSE); | |
| 268 close_button_ = close; | |
| 269 } else { | |
| 270 close_button_ = new views::ImageButton(this); | |
| 271 close_button_->set_request_focus_on_press(true); | |
| 272 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 273 close_button_->SetImage(views::CustomButton::STATE_NORMAL, | |
| 274 rb.GetImageNamed(IDR_CLOSE_1).ToImageSkia()); | |
| 275 close_button_->SetImage(views::CustomButton::STATE_HOVERED, | |
| 276 rb.GetImageNamed(IDR_CLOSE_1_H).ToImageSkia()); | |
| 277 close_button_->SetImage(views::CustomButton::STATE_PRESSED, | |
| 278 rb.GetImageNamed(IDR_CLOSE_1_P).ToImageSkia()); | |
| 279 } | |
| 280 close_button_->SetAccessibleName( | 178 close_button_->SetAccessibleName( |
| 281 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); | 179 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); |
| 282 close_button_->SetFocusForPlatform(); | 180 close_button_->SetFocusForPlatform(); |
| 283 // Subclasses should already be done adding child views by this point (see | 181 // Subclasses should already be done adding child views by this point (see |
| 284 // related DCHECK in Layout()). | 182 // related DCHECK in Layout()). |
| 285 child_container_->AddChildView(close_button_); | 183 child_container_->AddChildView(close_button_); |
| 286 } | 184 } |
| 287 | 185 |
| 288 // Ensure the infobar is tall enough to display its contents. | 186 // Ensure the infobar is tall enough to display its contents. |
| 289 int height = ui::MaterialDesignController::IsModeMaterial() | 187 int height = InfoBarContainerDelegate::kDefaultBarTargetHeightMd; |
|
Peter Kasting
2016/09/19 19:04:06
It'd be nice to rename this to drop the "md" suffi
Evan Stade
2016/09/19 20:06:02
Yea, we can/should rename this, but only when mac
| |
| 290 ? InfoBarContainerDelegate::kDefaultBarTargetHeightMd | |
| 291 : InfoBarContainerDelegate::kDefaultBarTargetHeight; | |
| 292 const int kMinimumVerticalPadding = 6; | 188 const int kMinimumVerticalPadding = 6; |
| 293 for (int i = 0; i < child_container_->child_count(); ++i) { | 189 for (int i = 0; i < child_container_->child_count(); ++i) { |
| 294 const int child_height = child_container_->child_at(i)->height(); | 190 const int child_height = child_container_->child_at(i)->height(); |
| 295 height = std::max(height, child_height + kMinimumVerticalPadding); | 191 height = std::max(height, child_height + kMinimumVerticalPadding); |
| 296 } | 192 } |
| 297 SetBarTargetHeight(height); | 193 SetBarTargetHeight(height); |
| 298 } | 194 } |
| 299 | 195 |
| 300 void InfoBarView::ButtonPressed(views::Button* sender, | 196 void InfoBarView::ButtonPressed(views::Button* sender, |
| 301 const ui::Event& event) { | 197 const ui::Event& event) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 430 } | 326 } |
| 431 | 327 |
| 432 bool InfoBarView::DoesIntersectRect(const View* target, | 328 bool InfoBarView::DoesIntersectRect(const View* target, |
| 433 const gfx::Rect& rect) const { | 329 const gfx::Rect& rect) const { |
| 434 DCHECK_EQ(this, target); | 330 DCHECK_EQ(this, target); |
| 435 // Only events that intersect the portion below the arrow are interesting. | 331 // Only events that intersect the portion below the arrow are interesting. |
| 436 gfx::Rect non_arrow_bounds = GetLocalBounds(); | 332 gfx::Rect non_arrow_bounds = GetLocalBounds(); |
| 437 non_arrow_bounds.Inset(0, arrow_height(), 0, 0); | 333 non_arrow_bounds.Inset(0, arrow_height(), 0, 0); |
| 438 return rect.Intersects(non_arrow_bounds); | 334 return rect.Intersects(non_arrow_bounds); |
| 439 } | 335 } |
| OLD | NEW |