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