Home | History | Annotate | Download | only in views
      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/tab_icon_view.h"
      6 
      7 #if defined(OS_WIN)
      8 #include <windows.h>
      9 #include <shellapi.h>
     10 #endif
     11 
     12 #include "base/logging.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "chrome/app/chrome_command_ids.h"
     15 #include "chrome/browser/ui/views/tab_icon_view_model.h"
     16 #include "grit/theme_resources.h"
     17 #include "grit/ui_resources.h"
     18 #include "ui/base/resource/resource_bundle.h"
     19 #include "ui/base/theme_provider.h"
     20 #include "ui/gfx/canvas.h"
     21 #include "ui/gfx/favicon_size.h"
     22 
     23 #if defined(OS_WIN)
     24 #include "chrome/browser/app_icon_win.h"
     25 #include "ui/gfx/icon_util.h"
     26 #endif
     27 
     28 static bool g_initialized = false;
     29 static gfx::ImageSkia* g_default_favicon = NULL;
     30 
     31 // static
     32 void TabIconView::InitializeIfNeeded() {
     33   if (!g_initialized) {
     34     g_initialized = true;
     35 
     36 #if defined(OS_WIN)
     37     // The default window icon is the application icon, not the default
     38     // favicon.
     39     HICON app_icon = GetAppIcon();
     40     scoped_ptr<SkBitmap> bitmap(
     41         IconUtil::CreateSkBitmapFromHICON(app_icon, gfx::Size(16, 16)));
     42     g_default_favicon = new gfx::ImageSkia(gfx::ImageSkiaRep(*bitmap, 1.0f));
     43     DestroyIcon(app_icon);
     44 #else
     45     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
     46     g_default_favicon = rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_16);
     47 #endif
     48   }
     49 }
     50 
     51 TabIconView::TabIconView(chrome::TabIconViewModel* model,
     52                          views::MenuButtonListener* listener)
     53     : views::MenuButton(NULL, base::string16(), listener, false),
     54       model_(model),
     55       throbber_running_(false),
     56       is_light_(false),
     57       throbber_frame_(0) {
     58   InitializeIfNeeded();
     59 }
     60 
     61 TabIconView::~TabIconView() {
     62 }
     63 
     64 void TabIconView::Update() {
     65   static bool initialized = false;
     66   static int throbber_frame_count = 0;
     67   if (!initialized) {
     68     initialized = true;
     69     gfx::ImageSkia throbber(*ui::ResourceBundle::GetSharedInstance().
     70         GetImageSkiaNamed(IDR_THROBBER));
     71     throbber_frame_count = throbber.width() / throbber.height();
     72   }
     73 
     74   if (throbber_running_) {
     75     // We think the tab is loading.
     76     if (!model_->ShouldTabIconViewAnimate()) {
     77       // Woops, tab is invalid or not loading, reset our status and schedule
     78       // a paint.
     79       throbber_running_ = false;
     80       SchedulePaint();
     81     } else {
     82       // The tab is still loading, increment the frame.
     83       throbber_frame_ = (throbber_frame_ + 1) % throbber_frame_count;
     84       SchedulePaint();
     85     }
     86   } else if (model_->ShouldTabIconViewAnimate()) {
     87     // We didn't think we were loading, but the tab is loading. Reset the
     88     // frame and status and schedule a paint.
     89     throbber_running_ = true;
     90     throbber_frame_ = 0;
     91     SchedulePaint();
     92   }
     93 }
     94 
     95 void TabIconView::PaintThrobber(gfx::Canvas* canvas) {
     96   gfx::ImageSkia throbber(*GetThemeProvider()->GetImageSkiaNamed(
     97       is_light_ ? IDR_THROBBER_LIGHT : IDR_THROBBER));
     98   int image_size = throbber.height();
     99   PaintIcon(canvas, throbber, throbber_frame_ * image_size, 0, image_size,
    100             image_size, false);
    101 }
    102 
    103 void TabIconView::PaintFavicon(gfx::Canvas* canvas,
    104                                const gfx::ImageSkia& image) {
    105   PaintIcon(canvas, image, 0, 0, image.width(), image.height(), true);
    106 }
    107 
    108 void TabIconView::PaintIcon(gfx::Canvas* canvas,
    109                             const gfx::ImageSkia& image,
    110                             int src_x,
    111                             int src_y,
    112                             int src_w,
    113                             int src_h,
    114                             bool filter) {
    115   // For source images smaller than the favicon square, scale them as if they
    116   // were padded to fit the favicon square, so we don't blow up tiny favicons
    117   // into larger or nonproportional results.
    118   float float_src_w = static_cast<float>(src_w);
    119   float float_src_h = static_cast<float>(src_h);
    120   float scalable_w, scalable_h;
    121   if (src_w <= gfx::kFaviconSize && src_h <= gfx::kFaviconSize) {
    122     scalable_w = scalable_h = gfx::kFaviconSize;
    123   } else {
    124     scalable_w = float_src_w;
    125     scalable_h = float_src_h;
    126   }
    127 
    128   // Scale proportionately.
    129   float scale = std::min(static_cast<float>(width()) / scalable_w,
    130                          static_cast<float>(height()) / scalable_h);
    131   int dest_w = static_cast<int>(float_src_w * scale);
    132   int dest_h = static_cast<int>(float_src_h * scale);
    133 
    134   // Center the scaled image.
    135   canvas->DrawImageInt(image, src_x, src_y, src_w, src_h,
    136                        (width() - dest_w) / 2, (height() - dest_h) / 2, dest_w,
    137                        dest_h, filter);
    138 }
    139 
    140 void TabIconView::OnPaint(gfx::Canvas* canvas) {
    141   bool rendered = false;
    142 
    143   if (throbber_running_) {
    144     rendered = true;
    145     PaintThrobber(canvas);
    146   } else {
    147     gfx::ImageSkia favicon = model_->GetFaviconForTabIconView();
    148     if (!favicon.isNull()) {
    149       rendered = true;
    150       PaintFavicon(canvas, favicon);
    151     }
    152   }
    153 
    154   if (!rendered)
    155     PaintFavicon(canvas, *g_default_favicon);
    156 }
    157 
    158 gfx::Size TabIconView::GetPreferredSize() const {
    159   return gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize);
    160 }
    161