| 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" | |
| 24 #include "ui/gfx/canvas.h" | 22 #include "ui/gfx/canvas.h" |
| 25 #include "ui/gfx/color_palette.h" | 23 #include "ui/gfx/color_palette.h" |
| 26 #include "ui/gfx/image/image.h" | 24 #include "ui/gfx/image/image.h" |
| 27 #include "ui/gfx/paint_vector_icon.h" | 25 #include "ui/gfx/paint_vector_icon.h" |
| 28 #include "ui/gfx/vector_icons_public.h" | 26 #include "ui/gfx/vector_icons_public.h" |
| 29 #include "ui/native_theme/common_theme.h" | 27 #include "ui/native_theme/common_theme.h" |
| 30 #include "ui/native_theme/native_theme.h" | 28 #include "ui/native_theme/native_theme.h" |
| 31 #include "ui/resources/grit/ui_resources.h" | |
| 32 #include "ui/views/controls/button/image_button.h" | 29 #include "ui/views/controls/button/image_button.h" |
| 33 #include "ui/views/controls/button/label_button.h" | |
| 34 #include "ui/views/controls/button/label_button_border.h" | 30 #include "ui/views/controls/button/label_button_border.h" |
| 35 #include "ui/views/controls/button/md_text_button.h" | 31 #include "ui/views/controls/button/md_text_button.h" |
| 36 #include "ui/views/controls/button/menu_button.h" | 32 #include "ui/views/controls/button/menu_button.h" |
| 37 #include "ui/views/controls/button/vector_icon_button.h" | 33 #include "ui/views/controls/button/vector_icon_button.h" |
| 38 #include "ui/views/controls/image_view.h" | 34 #include "ui/views/controls/image_view.h" |
| 39 #include "ui/views/controls/label.h" | 35 #include "ui/views/controls/label.h" |
| 40 #include "ui/views/controls/link.h" | 36 #include "ui/views/controls/link.h" |
| 41 #include "ui/views/controls/menu/menu_runner.h" | 37 #include "ui/views/controls/menu/menu_runner.h" |
| 42 #include "ui/views/layout/layout_constants.h" | 38 #include "ui/views/layout/layout_constants.h" |
| 43 #include "ui/views/widget/widget.h" | 39 #include "ui/views/widget/widget.h" |
| 44 #include "ui/views/window/non_client_view.h" | 40 #include "ui/views/window/non_client_view.h" |
| 45 | 41 |
| 46 | 42 |
| 47 // Helpers -------------------------------------------------------------------- | 43 // Helpers -------------------------------------------------------------------- |
| 48 | 44 |
| 49 namespace { | 45 namespace { |
| 50 | 46 |
| 51 const int kEdgeItemPadding = views::kRelatedControlHorizontalSpacing; | 47 const int kEdgeItemPadding = views::kRelatedControlHorizontalSpacing; |
| 52 const int kIconToLabelSpacing = views::kRelatedControlHorizontalSpacing; | 48 const int kIconToLabelSpacing = views::kRelatedControlHorizontalSpacing; |
| 53 const int kBeforeCloseButtonSpacing = views::kUnrelatedControlHorizontalSpacing; | 49 const int kBeforeCloseButtonSpacing = views::kUnrelatedControlHorizontalSpacing; |
| 54 | 50 |
| 55 bool SortLabelsByDecreasingWidth(views::Label* label_1, views::Label* label_2) { | 51 bool SortLabelsByDecreasingWidth(views::Label* label_1, views::Label* label_2) { |
| 56 return label_1->GetPreferredSize().width() > | 52 return label_1->GetPreferredSize().width() > |
| 57 label_2->GetPreferredSize().width(); | 53 label_2->GetPreferredSize().width(); |
| 58 } | 54 } |
| 59 | 55 |
| 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() { | 56 constexpr SkColor GetInfobarTextColor() { |
| 68 return SK_ColorBLACK; | 57 return SK_ColorBLACK; |
| 69 } | 58 } |
| 70 | 59 |
| 71 } // namespace | 60 } // namespace |
| 72 | 61 |
| 73 | 62 |
| 74 // InfoBarView ---------------------------------------------------------------- | 63 // InfoBarView ---------------------------------------------------------------- |
| 75 | 64 |
| 76 // static | 65 // static |
| (...skipping 10 matching lines...) Expand all Loading... |
| 87 set_owned_by_client(); // InfoBar deletes itself at the appropriate time. | 76 set_owned_by_client(); // InfoBar deletes itself at the appropriate time. |
| 88 set_background( | 77 set_background( |
| 89 new InfoBarBackground(infobars::InfoBar::delegate()->GetInfoBarType())); | 78 new InfoBarBackground(infobars::InfoBar::delegate()->GetInfoBarType())); |
| 90 SetEventTargeter(base::MakeUnique<views::ViewTargeter>(this)); | 79 SetEventTargeter(base::MakeUnique<views::ViewTargeter>(this)); |
| 91 | 80 |
| 92 AddChildView(child_container_); | 81 AddChildView(child_container_); |
| 93 | 82 |
| 94 SetPaintToLayer(true); | 83 SetPaintToLayer(true); |
| 95 layer()->SetFillsBoundsOpaquely(false); | 84 layer()->SetFillsBoundsOpaquely(false); |
| 96 | 85 |
| 97 if (ui::MaterialDesignController::IsModeMaterial()) { | 86 child_container_->SetPaintToLayer(true); |
| 98 child_container_->SetPaintToLayer(true); | 87 child_container_->layer()->SetMasksToBounds(true); |
| 99 child_container_->layer()->SetMasksToBounds(true); | 88 child_container_->set_background( |
| 100 // Since MD doesn't use a gradient, we can set a solid bg color. | 89 views::Background::CreateSolidBackground(infobars::InfoBar::GetTopColor( |
| 101 child_container_->set_background( | 90 infobars::InfoBar::delegate()->GetInfoBarType()))); |
| 102 views::Background::CreateSolidBackground(infobars::InfoBar::GetTopColor( | |
| 103 infobars::InfoBar::delegate()->GetInfoBarType()))); | |
| 104 } | |
| 105 } | 91 } |
| 106 | 92 |
| 107 const infobars::InfoBarContainer::Delegate* InfoBarView::container_delegate() | 93 const infobars::InfoBarContainer::Delegate* InfoBarView::container_delegate() |
| 108 const { | 94 const { |
| 109 const infobars::InfoBarContainer* infobar_container = container(); | 95 const infobars::InfoBarContainer* infobar_container = container(); |
| 110 return infobar_container ? infobar_container->delegate() : NULL; | 96 return infobar_container ? infobar_container->delegate() : NULL; |
| 111 } | 97 } |
| 112 | 98 |
| 113 InfoBarView::~InfoBarView() { | 99 InfoBarView::~InfoBarView() { |
| 114 // We should have closed any open menus in PlatformSpecificHide(), then | 100 // We should have closed any open menus in PlatformSpecificHide(), then |
| 115 // subclasses' RunMenu() functions should have prevented opening any new ones | 101 // subclasses' RunMenu() functions should have prevented opening any new ones |
| 116 // once we became unowned. | 102 // once we became unowned. |
| 117 DCHECK(!menu_runner_.get()); | 103 DCHECK(!menu_runner_.get()); |
| 118 } | 104 } |
| 119 | 105 |
| 120 views::Label* InfoBarView::CreateLabel(const base::string16& text) const { | 106 views::Label* InfoBarView::CreateLabel(const base::string16& text) const { |
| 121 views::Label* label = new views::Label(text, GetFontList()); | 107 views::Label* label = new views::Label(text); |
| 122 label->SizeToPreferredSize(); | 108 label->SizeToPreferredSize(); |
| 123 label->SetBackgroundColor(background()->get_color()); | 109 label->SetBackgroundColor(background()->get_color()); |
| 124 label->SetEnabledColor(GetInfobarTextColor()); | 110 label->SetEnabledColor(GetInfobarTextColor()); |
| 125 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 111 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 126 return label; | 112 return label; |
| 127 } | 113 } |
| 128 | 114 |
| 129 views::Link* InfoBarView::CreateLink(const base::string16& text, | 115 views::Link* InfoBarView::CreateLink(const base::string16& text, |
| 130 views::LinkListener* listener) const { | 116 views::LinkListener* listener) const { |
| 131 views::Link* link = new views::Link(text); | 117 views::Link* link = new views::Link(text); |
| 132 link->SetFontList(GetFontList()); | |
| 133 link->SizeToPreferredSize(); | 118 link->SizeToPreferredSize(); |
| 134 link->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 119 link->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 135 link->set_listener(listener); | 120 link->set_listener(listener); |
| 136 link->SetBackgroundColor(background()->get_color()); | 121 link->SetBackgroundColor(background()->get_color()); |
| 137 return link; | 122 return link; |
| 138 } | 123 } |
| 139 | 124 |
| 140 // static | 125 // 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); | |
| 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) { | 126 void InfoBarView::AssignWidths(Labels* labels, int available_width) { |
| 173 std::sort(labels->begin(), labels->end(), SortLabelsByDecreasingWidth); | 127 std::sort(labels->begin(), labels->end(), SortLabelsByDecreasingWidth); |
| 174 AssignWidthsSorted(labels, available_width); | 128 AssignWidthsSorted(labels, available_width); |
| 175 } | 129 } |
| 176 | 130 |
| 177 void InfoBarView::Layout() { | 131 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( | 132 child_container_->SetBounds( |
| 225 0, arrow_height(), width(), | 133 0, arrow_height(), width(), |
| 226 bar_height() - InfoBarContainerDelegate::kSeparatorLineHeight); | 134 bar_height() - InfoBarContainerDelegate::kSeparatorLineHeight); |
| 227 // |child_container_| should be the only child. | 135 // |child_container_| should be the only child. |
| 228 DCHECK_EQ(1, child_count()); | 136 DCHECK_EQ(1, child_count()); |
| 229 | 137 |
| 230 // Even though other views are technically grandchildren, we'll lay them out | 138 // Even though other views are technically grandchildren, we'll lay them out |
| 231 // here on behalf of |child_container_|. | 139 // here on behalf of |child_container_|. |
| 232 int start_x = kEdgeItemPadding; | 140 int start_x = kEdgeItemPadding; |
| 233 if (icon_ != NULL) { | 141 if (icon_ != NULL) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 255 | 163 |
| 256 if (details.is_add && (details.child == this) && (close_button_ == NULL)) { | 164 if (details.is_add && (details.child == this) && (close_button_ == NULL)) { |
| 257 gfx::Image image = delegate()->GetIcon(); | 165 gfx::Image image = delegate()->GetIcon(); |
| 258 if (!image.IsEmpty()) { | 166 if (!image.IsEmpty()) { |
| 259 icon_ = new views::ImageView; | 167 icon_ = new views::ImageView; |
| 260 icon_->SetImage(image.ToImageSkia()); | 168 icon_->SetImage(image.ToImageSkia()); |
| 261 icon_->SizeToPreferredSize(); | 169 icon_->SizeToPreferredSize(); |
| 262 child_container_->AddChildView(icon_); | 170 child_container_->AddChildView(icon_); |
| 263 } | 171 } |
| 264 | 172 |
| 265 if (ui::MaterialDesignController::IsModeMaterial()) { | 173 close_button_ = new views::VectorIconButton(this); |
| 266 views::VectorIconButton* close = new views::VectorIconButton(this); | 174 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( | 175 close_button_->SetAccessibleName( |
| 281 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); | 176 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); |
| 282 close_button_->SetFocusForPlatform(); | 177 close_button_->SetFocusForPlatform(); |
| 283 // Subclasses should already be done adding child views by this point (see | 178 // Subclasses should already be done adding child views by this point (see |
| 284 // related DCHECK in Layout()). | 179 // related DCHECK in Layout()). |
| 285 child_container_->AddChildView(close_button_); | 180 child_container_->AddChildView(close_button_); |
| 286 } | 181 } |
| 287 | 182 |
| 288 // Ensure the infobar is tall enough to display its contents. | 183 // Ensure the infobar is tall enough to display its contents. |
| 289 int height = ui::MaterialDesignController::IsModeMaterial() | 184 int height = InfoBarContainerDelegate::kDefaultBarTargetHeightMd; |
| 290 ? InfoBarContainerDelegate::kDefaultBarTargetHeightMd | |
| 291 : InfoBarContainerDelegate::kDefaultBarTargetHeight; | |
| 292 const int kMinimumVerticalPadding = 6; | 185 const int kMinimumVerticalPadding = 6; |
| 293 for (int i = 0; i < child_container_->child_count(); ++i) { | 186 for (int i = 0; i < child_container_->child_count(); ++i) { |
| 294 const int child_height = child_container_->child_at(i)->height(); | 187 const int child_height = child_container_->child_at(i)->height(); |
| 295 height = std::max(height, child_height + kMinimumVerticalPadding); | 188 height = std::max(height, child_height + kMinimumVerticalPadding); |
| 296 } | 189 } |
| 297 SetBarTargetHeight(height); | 190 SetBarTargetHeight(height); |
| 298 } | 191 } |
| 299 | 192 |
| 300 void InfoBarView::ButtonPressed(views::Button* sender, | 193 void InfoBarView::ButtonPressed(views::Button* sender, |
| 301 const ui::Event& event) { | 194 const ui::Event& event) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 } | 323 } |
| 431 | 324 |
| 432 bool InfoBarView::DoesIntersectRect(const View* target, | 325 bool InfoBarView::DoesIntersectRect(const View* target, |
| 433 const gfx::Rect& rect) const { | 326 const gfx::Rect& rect) const { |
| 434 DCHECK_EQ(this, target); | 327 DCHECK_EQ(this, target); |
| 435 // Only events that intersect the portion below the arrow are interesting. | 328 // Only events that intersect the portion below the arrow are interesting. |
| 436 gfx::Rect non_arrow_bounds = GetLocalBounds(); | 329 gfx::Rect non_arrow_bounds = GetLocalBounds(); |
| 437 non_arrow_bounds.Inset(0, arrow_height(), 0, 0); | 330 non_arrow_bounds.Inset(0, arrow_height(), 0, 0); |
| 438 return rect.Intersects(non_arrow_bounds); | 331 return rect.Intersects(non_arrow_bounds); |
| 439 } | 332 } |
| OLD | NEW |