Home | History | Annotate | Download | only in controls
      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/image_view.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "third_party/skia/include/core/SkPaint.h"
     10 #include "ui/base/accessibility/accessible_view_state.h"
     11 #include "ui/gfx/canvas.h"
     12 #include "ui/gfx/insets.h"
     13 
     14 namespace views {
     15 
     16 ImageView::ImageView()
     17     : image_size_set_(false),
     18       horiz_alignment_(CENTER),
     19       vert_alignment_(CENTER),
     20       interactive_(true) {
     21 }
     22 
     23 ImageView::~ImageView() {
     24 }
     25 
     26 void ImageView::SetImage(const gfx::ImageSkia& img) {
     27   gfx::Size pref_size(GetPreferredSize());
     28   image_ = img;
     29   if (pref_size != GetPreferredSize())
     30     PreferredSizeChanged();
     31   SchedulePaint();
     32 }
     33 
     34 void ImageView::SetImage(const gfx::ImageSkia* image_skia) {
     35   if (image_skia) {
     36     SetImage(*image_skia);
     37   } else {
     38     gfx::ImageSkia t;
     39     SetImage(t);
     40   }
     41 }
     42 
     43 const gfx::ImageSkia& ImageView::GetImage() {
     44   return image_;
     45 }
     46 
     47 void ImageView::SetImageSize(const gfx::Size& image_size) {
     48   image_size_set_ = true;
     49   image_size_ = image_size;
     50   PreferredSizeChanged();
     51 }
     52 
     53 bool ImageView::GetImageSize(gfx::Size* image_size) {
     54   DCHECK(image_size);
     55   if (image_size_set_)
     56     *image_size = image_size_;
     57   return image_size_set_;
     58 }
     59 
     60 gfx::Rect ImageView::GetImageBounds() const {
     61   gfx::Size image_size(image_size_set_ ?
     62     image_size_ : gfx::Size(image_.width(), image_.height()));
     63   return gfx::Rect(ComputeImageOrigin(image_size), image_size);
     64 }
     65 
     66 void ImageView::ResetImageSize() {
     67   image_size_set_ = false;
     68 }
     69 
     70 gfx::Size ImageView::GetPreferredSize() {
     71   gfx::Insets insets = GetInsets();
     72   if (image_size_set_) {
     73     gfx::Size image_size;
     74     GetImageSize(&image_size);
     75     image_size.Enlarge(insets.width(), insets.height());
     76     return image_size;
     77   }
     78   return gfx::Size(image_.width() + insets.width(),
     79                    image_.height() + insets.height());
     80 }
     81 
     82 gfx::Point ImageView::ComputeImageOrigin(const gfx::Size& image_size) const {
     83   gfx::Insets insets = GetInsets();
     84 
     85   int x;
     86   // In order to properly handle alignment of images in RTL locales, we need
     87   // to flip the meaning of trailing and leading. For example, if the
     88   // horizontal alignment is set to trailing, then we'll use left alignment for
     89   // the image instead of right alignment if the UI layout is RTL.
     90   Alignment actual_horiz_alignment = horiz_alignment_;
     91   if (base::i18n::IsRTL() && (horiz_alignment_ != CENTER))
     92     actual_horiz_alignment = (horiz_alignment_ == LEADING) ? TRAILING : LEADING;
     93   switch (actual_horiz_alignment) {
     94     case LEADING:  x = insets.left();                                 break;
     95     case TRAILING: x = width() - insets.right() - image_size.width(); break;
     96     case CENTER:   x = (width() - image_size.width()) / 2;            break;
     97     default:       NOTREACHED(); x = 0;                               break;
     98   }
     99 
    100   int y;
    101   switch (vert_alignment_) {
    102     case LEADING:  y = insets.top();                                     break;
    103     case TRAILING: y = height() - insets.bottom() - image_size.height(); break;
    104     case CENTER:   y = (height() - image_size.height()) / 2;             break;
    105     default:       NOTREACHED(); y = 0;                                  break;
    106   }
    107 
    108   return gfx::Point(x, y);
    109 }
    110 
    111 void ImageView::OnPaint(gfx::Canvas* canvas) {
    112   View::OnPaint(canvas);
    113 
    114   if (image_.isNull())
    115     return;
    116 
    117   gfx::Rect image_bounds(GetImageBounds());
    118   if (image_bounds.IsEmpty())
    119     return;
    120 
    121   if (image_bounds.size() != gfx::Size(image_.width(), image_.height())) {
    122     // Resize case
    123     SkPaint paint;
    124     paint.setFilterBitmap(true);
    125     canvas->DrawImageInt(image_, 0, 0, image_.width(), image_.height(),
    126         image_bounds.x(), image_bounds.y(), image_bounds.width(),
    127         image_bounds.height(), true, paint);
    128   } else {
    129     canvas->DrawImageInt(image_, image_bounds.x(), image_bounds.y());
    130   }
    131 }
    132 
    133 void ImageView::GetAccessibleState(ui::AccessibleViewState* state) {
    134   state->role = ui::AccessibilityTypes::ROLE_GRAPHIC;
    135   state->name = tooltip_text_;
    136 }
    137 
    138 void ImageView::SetHorizontalAlignment(Alignment ha) {
    139   if (ha != horiz_alignment_) {
    140     horiz_alignment_ = ha;
    141     SchedulePaint();
    142   }
    143 }
    144 
    145 ImageView::Alignment ImageView::GetHorizontalAlignment() const {
    146   return horiz_alignment_;
    147 }
    148 
    149 void ImageView::SetVerticalAlignment(Alignment va) {
    150   if (va != vert_alignment_) {
    151     vert_alignment_ = va;
    152     SchedulePaint();
    153   }
    154 }
    155 
    156 ImageView::Alignment ImageView::GetVerticalAlignment() const {
    157   return vert_alignment_;
    158 }
    159 
    160 void ImageView::SetTooltipText(const string16& tooltip) {
    161   tooltip_text_ = tooltip;
    162 }
    163 
    164 string16 ImageView::GetTooltipText() const {
    165   return tooltip_text_;
    166 }
    167 
    168 bool ImageView::GetTooltipText(const gfx::Point& p, string16* tooltip) const {
    169   if (tooltip_text_.empty())
    170     return false;
    171 
    172   *tooltip = GetTooltipText();
    173   return true;
    174 }
    175 
    176 bool ImageView::HitTestRect(const gfx::Rect& rect) const {
    177   return interactive_ ? View::HitTestRect(rect) : false;
    178 }
    179 
    180 }  // namespace views
    181