Home | History | Annotate | Download | only in menu
      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 "ui/views/controls/menu/menu_image_util.h"
      6 
      7 #include "base/i18n/rtl.h"
      8 #include "base/logging.h"
      9 #include "grit/ui_resources.h"
     10 #include "third_party/skia/include/effects/SkGradientShader.h"
     11 #include "ui/base/resource/resource_bundle.h"
     12 #include "ui/gfx/canvas.h"
     13 #include "ui/gfx/image/canvas_image_source.h"
     14 #include "ui/gfx/image/image.h"
     15 #include "ui/gfx/image/image_skia.h"
     16 #include "ui/gfx/image/image_skia_source.h"
     17 #include "ui/gfx/point.h"
     18 #include "ui/gfx/size.h"
     19 
     20 namespace {
     21 
     22 // Size of the radio button inciator.
     23 const int kSelectedIndicatorSize = 5;
     24 const int kIndicatorSize = 10;
     25 
     26 // Used for the radio indicator. See theme_draw for details.
     27 const double kGradientStop = .5;
     28 const SkColor kGradient0 = SkColorSetRGB(255, 255, 255);
     29 const SkColor kGradient1 = SkColorSetRGB(255, 255, 255);
     30 const SkColor kGradient2 = SkColorSetRGB(0xD8, 0xD8, 0xD8);
     31 const SkColor kBaseStroke = SkColorSetRGB(0x8F, 0x8F, 0x8F);
     32 const SkColor kRadioButtonIndicatorGradient0 = SkColorSetRGB(0, 0, 0);
     33 const SkColor kRadioButtonIndicatorGradient1 = SkColorSetRGB(0x83, 0x83, 0x83);
     34 const SkColor kIndicatorStroke = SkColorSetRGB(0, 0, 0);
     35 
     36 class RadioButtonImageSource : public gfx::CanvasImageSource {
     37  public:
     38   explicit RadioButtonImageSource(bool selected)
     39       : CanvasImageSource(gfx::Size(kIndicatorSize + 2, kIndicatorSize + 2),
     40                           false),
     41         selected_(selected) {
     42   }
     43   virtual ~RadioButtonImageSource() {}
     44 
     45   virtual void Draw(gfx::Canvas* canvas) OVERRIDE {
     46     canvas->Translate(gfx::Vector2d(1, 1));
     47 
     48     SkPoint gradient_points[3];
     49     gradient_points[0].iset(0, 0);
     50     gradient_points[1].iset(0,
     51                             static_cast<int>(kIndicatorSize * kGradientStop));
     52     gradient_points[2].iset(0, kIndicatorSize);
     53     SkColor gradient_colors[3] = { kGradient0, kGradient1, kGradient2 };
     54     skia::RefPtr<SkShader> shader = skia::AdoptRef(
     55         SkGradientShader::CreateLinear(
     56             gradient_points, gradient_colors, NULL, arraysize(gradient_points),
     57             SkShader::kClamp_TileMode, NULL));
     58     SkPaint paint;
     59     paint.setStyle(SkPaint::kFill_Style);
     60     paint.setAntiAlias(true);
     61     paint.setShader(shader.get());
     62     int radius = kIndicatorSize / 2;
     63     canvas->sk_canvas()->drawCircle(radius, radius, radius, paint);
     64     paint.setStrokeWidth(SkIntToScalar(0));
     65     paint.setShader(NULL);
     66     paint.setStyle(SkPaint::kStroke_Style);
     67     paint.setColor(kBaseStroke);
     68     canvas->sk_canvas()->drawCircle(radius, radius, radius, paint);
     69 
     70     if (selected_) {
     71       SkPoint selected_gradient_points[2];
     72       selected_gradient_points[0].iset(0, 0);
     73       selected_gradient_points[1].iset(0, kSelectedIndicatorSize);
     74       SkColor selected_gradient_colors[2] = { kRadioButtonIndicatorGradient0,
     75                                               kRadioButtonIndicatorGradient1 };
     76       shader = skia::AdoptRef(
     77           SkGradientShader::CreateLinear(
     78               selected_gradient_points, selected_gradient_colors, NULL,
     79               arraysize(selected_gradient_points),
     80               SkShader::kClamp_TileMode, NULL));
     81       paint.setShader(shader.get());
     82       paint.setStyle(SkPaint::kFill_Style);
     83       canvas->sk_canvas()->drawCircle(radius, radius,
     84                                       kSelectedIndicatorSize / 2, paint);
     85 
     86       paint.setStrokeWidth(SkIntToScalar(0));
     87       paint.setShader(NULL);
     88       paint.setStyle(SkPaint::kStroke_Style);
     89       paint.setColor(kIndicatorStroke);
     90       canvas->sk_canvas()->drawCircle(radius, radius,
     91                                       kSelectedIndicatorSize / 2, paint);
     92     }
     93   }
     94 
     95  private:
     96   bool selected_;
     97 
     98   DISALLOW_COPY_AND_ASSIGN(RadioButtonImageSource);
     99 };
    100 
    101 class SubmenuArrowImageSource : public gfx::CanvasImageSource {
    102  public:
    103   SubmenuArrowImageSource(int image_id)
    104       : gfx::CanvasImageSource(ui::ResourceBundle::GetSharedInstance().
    105             GetImageNamed(image_id).ToImageSkia()->size(), false),
    106         image_id_(image_id) {}
    107   virtual ~SubmenuArrowImageSource() {}
    108 
    109   virtual void Draw(gfx::Canvas* canvas) OVERRIDE {
    110     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    111     const gfx::ImageSkia* r = rb.GetImageNamed(image_id_).ToImageSkia();
    112     canvas->Scale(-1, 1);
    113     canvas->DrawImageInt(*r, - r->width(), 0);
    114   }
    115 
    116  private:
    117   static gfx::Size GetSubmenuArrowSize() {
    118     return ui::ResourceBundle::GetSharedInstance()
    119         .GetImageNamed(IDR_MENU_HIERARCHY_ARROW).ToImageSkia()->size();
    120   }
    121 
    122   int image_id_;
    123 
    124   DISALLOW_COPY_AND_ASSIGN(SubmenuArrowImageSource);
    125 };
    126 
    127 gfx::ImageSkia GetRtlSubmenuArrowImage(bool rtl,
    128                                        bool dark_background) {
    129   int image_id = dark_background ? IDR_MENU_HIERARCHY_ARROW_DARK_BACKGROUND :
    130                                    IDR_MENU_HIERARCHY_ARROW;
    131 
    132   if (!rtl) {
    133     return ui::ResourceBundle::GetSharedInstance().GetImageNamed(image_id).
    134         AsImageSkia();
    135   }
    136 
    137   static gfx::ImageSkia* kRtlArrow = NULL;
    138   static gfx::ImageSkia* kRtlArrowDarkBg = NULL;
    139   gfx::ImageSkia** image = dark_background ? &kRtlArrowDarkBg : &kRtlArrow;
    140 
    141   if (!*image) {
    142     SubmenuArrowImageSource* source = new SubmenuArrowImageSource(image_id);
    143     *image = new gfx::ImageSkia(source, source->size());
    144   }
    145 
    146   return **image;
    147 }
    148 
    149 }  // namespace
    150 
    151 namespace views {
    152 
    153 gfx::ImageSkia GetMenuCheckImage(bool dark_background) {
    154   int image_id = dark_background ? IDR_MENU_CHECK_CHECKED_DARK_BACKGROUND :
    155                                    IDR_MENU_CHECK_CHECKED;
    156   return ui::ResourceBundle::GetSharedInstance().GetImageNamed(image_id).
    157       AsImageSkia();
    158 }
    159 
    160 gfx::ImageSkia GetRadioButtonImage(bool selected) {
    161   int image_id = selected ? IDR_MENU_RADIO_SELECTED : IDR_MENU_RADIO_EMPTY;
    162   return ui::ResourceBundle::GetSharedInstance().GetImageNamed(image_id).
    163       AsImageSkia();
    164 }
    165 
    166 gfx::ImageSkia GetSubmenuArrowImage(bool dark_background) {
    167   return GetRtlSubmenuArrowImage(base::i18n::IsRTL(), dark_background);
    168 }
    169 
    170 }  // namespace views
    171