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