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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
9 #include "ui/base/resource/resource_bundle.h"
10 #include "ui/gfx/canvas.h"
11 #include "ui/gfx/color_utils.h"
12 #include "ui/views/controls/image_view.h"
13 #include "ui/views/painter.h"
14
15
IconLabelBubbleView(const int background_images[],const int hover_background_images[],int contained_image,const gfx::FontList & font_list,SkColor text_color,SkColor parent_background_color,bool elide_in_middle)16 IconLabelBubbleView::IconLabelBubbleView(const int background_images[],
17 const int hover_background_images[],
18 int contained_image,
19 const gfx::FontList& font_list,
20 SkColor text_color,
21 SkColor parent_background_color,
22 bool elide_in_middle)
23 : background_painter_(
24 views::Painter::CreateImageGridPainter(background_images)),
25 image_(new views::ImageView()),
26 label_(new views::Label(base::string16(), font_list)),
27 is_extension_icon_(false),
28 in_hover_(false) {
29 image_->SetImage(
30 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
31 contained_image));
32
33 // Disable separate hit testing for |image_|. This prevents views treating
34 // |image_| as a separate mouse hover region from |this|.
35 image_->set_interactive(false);
36 AddChildView(image_);
37
38 if (hover_background_images) {
39 hover_background_painter_.reset(
40 views::Painter::CreateImageGridPainter(hover_background_images));
41 }
42
43 label_->SetEnabledColor(text_color);
44 // Calculate the actual background color for the label. The background images
45 // are painted atop |parent_background_color|. We grab the color of the
46 // middle pixel of the middle image of the background, which we treat as the
47 // representative color of the entire background (reasonable, given the
48 // current appearance of these images). Then we alpha-blend it over the
49 // parent background color to determine the actual color the label text will
50 // sit atop.
51 const SkBitmap& bitmap(
52 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
53 background_images[4])->GetRepresentation(1.0f).sk_bitmap());
54 SkAutoLockPixels pixel_lock(bitmap);
55 SkColor background_image_color =
56 bitmap.getColor(bitmap.width() / 2, bitmap.height() / 2);
57 // Tricky bit: We alpha blend an opaque version of |background_image_color|
58 // against |parent_background_color| using the original image grid color's
59 // alpha. This is because AlphaBlend(a, b, 255) always returns |a| unchanged
60 // even if |a| is a color with non-255 alpha.
61 label_->SetBackgroundColor(
62 color_utils::AlphaBlend(SkColorSetA(background_image_color, 255),
63 parent_background_color,
64 SkColorGetA(background_image_color)));
65 if (elide_in_middle)
66 label_->SetElideBehavior(gfx::ELIDE_MIDDLE);
67 AddChildView(label_);
68 }
69
~IconLabelBubbleView()70 IconLabelBubbleView::~IconLabelBubbleView() {
71 }
72
SetLabel(const base::string16 & label)73 void IconLabelBubbleView::SetLabel(const base::string16& label) {
74 label_->SetText(label);
75 }
76
SetImage(const gfx::ImageSkia & image_skia)77 void IconLabelBubbleView::SetImage(const gfx::ImageSkia& image_skia) {
78 image_->SetImage(image_skia);
79 }
80
GetPreferredSize() const81 gfx::Size IconLabelBubbleView::GetPreferredSize() const {
82 // Height will be ignored by the LocationBarView.
83 return GetSizeForLabelWidth(label_->GetPreferredSize().width());
84 }
85
Layout()86 void IconLabelBubbleView::Layout() {
87 image_->SetBounds(GetBubbleOuterPadding(!is_extension_icon_), 0,
88 image_->GetPreferredSize().width(), height());
89 const int pre_label_width = GetPreLabelWidth();
90 label_->SetBounds(pre_label_width, 0,
91 width() - pre_label_width - GetBubbleOuterPadding(false),
92 height());
93 }
94
GetSizeForLabelWidth(int width) const95 gfx::Size IconLabelBubbleView::GetSizeForLabelWidth(int width) const {
96 gfx::Size size(GetPreLabelWidth() + width + GetBubbleOuterPadding(false), 0);
97 size.SetToMax(background_painter_->GetMinimumSize());
98 return size;
99 }
100
OnMouseEntered(const ui::MouseEvent & event)101 void IconLabelBubbleView::OnMouseEntered(const ui::MouseEvent& event) {
102 in_hover_ = true;
103 if (hover_background_painter_.get())
104 SchedulePaint();
105 }
106
OnMouseExited(const ui::MouseEvent & event)107 void IconLabelBubbleView::OnMouseExited(const ui::MouseEvent& event) {
108 in_hover_ = false;
109 if (hover_background_painter_.get())
110 SchedulePaint();
111 }
112
113 // static
GetBubbleOuterPadding(bool by_icon)114 int IconLabelBubbleView::GetBubbleOuterPadding(bool by_icon) {
115 return LocationBarView::kItemPadding - LocationBarView::kBubblePadding +
116 (by_icon ? 0 : LocationBarView::kIconInternalPadding);
117 }
118
OnPaint(gfx::Canvas * canvas)119 void IconLabelBubbleView::OnPaint(gfx::Canvas* canvas) {
120 views::Painter* painter = (in_hover_ && hover_background_painter_) ?
121 hover_background_painter_.get() : background_painter_.get();
122 painter->Paint(canvas, size());
123 }
124
GetPreLabelWidth() const125 int IconLabelBubbleView::GetPreLabelWidth() const {
126 const int image_width = image_->GetPreferredSize().width();
127 return GetBubbleOuterPadding(true) +
128 (image_width ? (image_width + LocationBarView::kItemPadding) : 0);
129 }
130