172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tab_icon_view.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <windows.h> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <shellapi.h> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/app/chrome_command_ids.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_resources.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/theme_provider.h" 1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas.h" 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/favicon_size.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/app_icon_win.h" 2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/icon_util.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool g_initialized = false; 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic SkBitmap* g_default_favicon = NULL; 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabIconView::InitializeIfNeeded() { 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!g_initialized) { 333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_initialized = true; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The default window icon is the application icon, not the default 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // favicon. 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HICON app_icon = GetAppIcon(); 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen g_default_favicon = 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IconUtil::CreateSkBitmapFromHICON(app_icon, gfx::Size(16, 16)); 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DestroyIcon(app_icon); 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen g_default_favicon = 443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_PRODUCT_LOGO_16); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabIconView::TabIconView(TabIconViewModel* model) 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : model_(model), 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch throbber_running_(false), 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch is_light_(false), 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch throbber_frame_(0) { 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InitializeIfNeeded(); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabIconView::~TabIconView() { 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabIconView::Update() { 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static bool initialized = false; 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static int throbber_frame_count = 0; 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!initialized) { 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick initialized = true; 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SkBitmap throbber( 663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_THROBBER)); 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick throbber_frame_count = throbber.width() / throbber.height(); 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (throbber_running_) { 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We think the tab is loading. 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!model_->ShouldTabIconViewAnimate()) { 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Woops, tab is invalid or not loading, reset our status and schedule 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a paint. 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch throbber_running_ = false; 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SchedulePaint(); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tab is still loading, increment the frame. 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick throbber_frame_ = (throbber_frame_ + 1) % throbber_frame_count; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SchedulePaint(); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (model_->ShouldTabIconViewAnimate()) { 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We didn't think we were loading, but the tab is loading. Reset the 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // frame and status and schedule a paint. 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch throbber_running_ = true; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch throbber_frame_ = 0; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SchedulePaint(); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabIconView::PaintThrobber(gfx::Canvas* canvas) { 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SkBitmap throbber(*GetThemeProvider()->GetBitmapNamed( 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick is_light_ ? IDR_THROBBER_LIGHT : IDR_THROBBER)); 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int image_size = throbber.height(); 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PaintIcon(canvas, throbber, throbber_frame_ * image_size, 0, image_size, 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick image_size, false); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TabIconView::PaintFavicon(gfx::Canvas* canvas, const SkBitmap& bitmap) { 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintIcon(canvas, bitmap, 0, 0, bitmap.width(), bitmap.height(), true); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabIconView::PaintIcon(gfx::Canvas* canvas, 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap& bitmap, 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int src_x, 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int src_y, 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int src_w, 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int src_h, 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool filter) { 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For source images smaller than the favicon square, scale them as if they 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // were padded to fit the favicon square, so we don't blow up tiny favicons 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // into larger or nonproportional results. 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float float_src_w = static_cast<float>(src_w); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float float_src_h = static_cast<float>(src_h); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float scalable_w, scalable_h; 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (src_w <= kFaviconSize && src_h <= kFaviconSize) { 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scalable_w = scalable_h = kFaviconSize; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scalable_w = float_src_w; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scalable_h = float_src_h; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Scale proportionately. 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float scale = std::min(static_cast<float>(width()) / scalable_w, 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<float>(height()) / scalable_h); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int dest_w = static_cast<int>(float_src_w * scale); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int dest_h = static_cast<int>(float_src_h * scale); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Center the scaled image. 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(bitmap, src_x, src_y, src_w, src_h, 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (width() - dest_w) / 2, (height() - dest_h) / 2, dest_w, 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dest_h, filter); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid TabIconView::OnPaint(gfx::Canvas* canvas) { 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool rendered = false; 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (throbber_running_) { 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rendered = true; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintThrobber(canvas); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SkBitmap favicon = model_->GetFaviconForTabIconView(); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!favicon.isNull()) { 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rendered = true; 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PaintFavicon(canvas, favicon); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!rendered) 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PaintFavicon(canvas, *g_default_favicon); 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size TabIconView::GetPreferredSize() { 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return gfx::Size(kFaviconSize, kFaviconSize); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 156