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