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