15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/color_utils.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/image_view.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/views/painter.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IconLabelBubbleView::IconLabelBubbleView(const int background_images[],
17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         const int hover_background_images[],
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int contained_image,
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                         const gfx::FontList& font_list,
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         SkColor text_color,
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         SkColor parent_background_color,
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         bool elide_in_middle)
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : background_painter_(
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          views::Painter::CreateImageGridPainter(background_images)),
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      image_(new views::ImageView()),
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      label_(new views::Label(base::string16(), font_list)),
27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      is_extension_icon_(false),
28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      in_hover_(false) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  image_->SetImage(
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          contained_image));
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Disable separate hit testing for |image_|.  This prevents views treating
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // |image_| as a separate mouse hover region from |this|.
35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  image_->set_interactive(false);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(image_);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (hover_background_images) {
39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    hover_background_painter_.reset(
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        views::Painter::CreateImageGridPainter(hover_background_images));
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  label_->SetEnabledColor(text_color);
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Calculate the actual background color for the label.  The background images
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // are painted atop |parent_background_color|.  We grab the color of the
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // middle pixel of the middle image of the background, which we treat as the
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // representative color of the entire background (reasonable, given the
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // current appearance of these images).  Then we alpha-blend it over the
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // parent background color to determine the actual color the label text will
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // sit atop.
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const SkBitmap& bitmap(
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          background_images[4])->GetRepresentation(1.0f).sk_bitmap());
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SkAutoLockPixels pixel_lock(bitmap);
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SkColor background_image_color =
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bitmap.getColor(bitmap.width() / 2, bitmap.height() / 2);
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Tricky bit: We alpha blend an opaque version of |background_image_color|
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // against |parent_background_color| using the original image grid color's
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // alpha. This is because AlphaBlend(a, b, 255) always returns |a| unchanged
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // even if |a| is a color with non-255 alpha.
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  label_->SetBackgroundColor(
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      color_utils::AlphaBlend(SkColorSetA(background_image_color, 255),
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              parent_background_color,
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              SkColorGetA(background_image_color)));
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (elide_in_middle)
6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    label_->SetElideBehavior(gfx::ELIDE_MIDDLE);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(label_);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IconLabelBubbleView::~IconLabelBubbleView() {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void IconLabelBubbleView::SetLabel(const base::string16& label) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  label_->SetText(label);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IconLabelBubbleView::SetImage(const gfx::ImageSkia& image_skia) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  image_->SetImage(image_skia);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size IconLabelBubbleView::GetPreferredSize() const {
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Height will be ignored by the LocationBarView.
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return GetSizeForLabelWidth(label_->GetPreferredSize().width());
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IconLabelBubbleView::Layout() {
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  image_->SetBounds(GetBubbleOuterPadding(!is_extension_icon_), 0,
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    image_->GetPreferredSize().width(), height());
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int pre_label_width = GetPreLabelWidth();
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  label_->SetBounds(pre_label_width, 0,
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    width() - pre_label_width - GetBubbleOuterPadding(false),
920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                    height());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)gfx::Size IconLabelBubbleView::GetSizeForLabelWidth(int width) const {
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  gfx::Size size(GetPreLabelWidth() + width + GetBubbleOuterPadding(false), 0);
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  size.SetToMax(background_painter_->GetMinimumSize());
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return size;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void IconLabelBubbleView::OnMouseEntered(const ui::MouseEvent& event) {
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  in_hover_ = true;
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (hover_background_painter_.get())
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    SchedulePaint();
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void IconLabelBubbleView::OnMouseExited(const ui::MouseEvent& event) {
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  in_hover_ = false;
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (hover_background_painter_.get())
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    SchedulePaint();
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int IconLabelBubbleView::GetBubbleOuterPadding(bool by_icon) {
1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return LocationBarView::kItemPadding - LocationBarView::kBubblePadding +
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      (by_icon ? 0 : LocationBarView::kIconInternalPadding);
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void IconLabelBubbleView::OnPaint(gfx::Canvas* canvas) {
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  views::Painter* painter = (in_hover_ && hover_background_painter_) ?
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      hover_background_painter_.get() : background_painter_.get();
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  painter->Paint(canvas, size());
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int IconLabelBubbleView::GetPreLabelWidth() const {
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int image_width = image_->GetPreferredSize().width();
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetBubbleOuterPadding(true) +
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      (image_width ? (image_width + LocationBarView::kItemPadding) : 0);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
130