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