| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/bubble/bubble_border.h" | 5 #include "ui/views/bubble/bubble_border.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | |
| 11 #include "grit/ui_resources.h" | 10 #include "grit/ui_resources.h" |
| 12 #include "ui/base/resource/resource_bundle.h" | 11 #include "ui/base/resource/resource_bundle.h" |
| 13 #include "ui/gfx/canvas.h" | 12 #include "ui/gfx/canvas.h" |
| 14 #include "ui/gfx/image/image_skia.h" | |
| 15 #include "ui/gfx/rect.h" | 13 #include "ui/gfx/rect.h" |
| 16 #include "ui/gfx/skia_util.h" | 14 #include "ui/gfx/skia_util.h" |
| 17 #include "ui/views/painter.h" | 15 #include "ui/views/painter.h" |
| 18 #include "ui/views/view.h" | 16 #include "ui/views/view.h" |
| 19 | 17 |
| 20 namespace views { | 18 namespace views { |
| 21 | 19 |
| 22 namespace internal { | 20 namespace internal { |
| 23 | 21 |
| 24 // A helper that combines each border image-set painter with arrows and metrics. | |
| 25 struct BorderImages { | |
| 26 BorderImages(const int border_image_ids[], | |
| 27 const int arrow_image_ids[], | |
| 28 int border_interior_thickness, | |
| 29 int arrow_interior_thickness, | |
| 30 int corner_radius); | |
| 31 | |
| 32 scoped_ptr<Painter> border_painter; | |
| 33 gfx::ImageSkia left_arrow; | |
| 34 gfx::ImageSkia top_arrow; | |
| 35 gfx::ImageSkia right_arrow; | |
| 36 gfx::ImageSkia bottom_arrow; | |
| 37 | |
| 38 // The thickness of border and arrow images and their interior areas. | |
| 39 // Thickness is the width of left/right and the height of top/bottom images. | |
| 40 // The interior is measured without including stroke or shadow pixels. | |
| 41 int border_thickness; | |
| 42 int border_interior_thickness; | |
| 43 int arrow_thickness; | |
| 44 int arrow_interior_thickness; | |
| 45 // The corner radius of the bubble's rounded-rect interior area. | |
| 46 int corner_radius; | |
| 47 }; | |
| 48 | |
| 49 BorderImages::BorderImages(const int border_image_ids[], | 22 BorderImages::BorderImages(const int border_image_ids[], |
| 50 const int arrow_image_ids[], | 23 const int arrow_image_ids[], |
| 51 int border_interior_thickness, | 24 int border_interior_thickness, |
| 52 int arrow_interior_thickness, | 25 int arrow_interior_thickness, |
| 53 int corner_radius) | 26 int corner_radius) |
| 54 : border_painter(Painter::CreateImageGridPainter(border_image_ids)), | 27 : border_painter(Painter::CreateImageGridPainter(border_image_ids)), |
| 55 border_thickness(0), | 28 border_thickness(0), |
| 56 border_interior_thickness(border_interior_thickness), | 29 border_interior_thickness(border_interior_thickness), |
| 57 arrow_thickness(0), | 30 arrow_thickness(0), |
| 58 arrow_interior_thickness(arrow_interior_thickness), | 31 arrow_interior_thickness(arrow_interior_thickness), |
| 59 corner_radius(corner_radius) { | 32 corner_radius(corner_radius) { |
| 60 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 33 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 61 border_thickness = rb.GetImageSkiaNamed(border_image_ids[0])->width(); | 34 border_thickness = rb.GetImageSkiaNamed(border_image_ids[0])->width(); |
| 62 if (arrow_image_ids[0] != 0) { | 35 if (arrow_image_ids[0] != 0) { |
| 63 left_arrow = *rb.GetImageSkiaNamed(arrow_image_ids[0]); | 36 left_arrow = *rb.GetImageSkiaNamed(arrow_image_ids[0]); |
| 64 top_arrow = *rb.GetImageSkiaNamed(arrow_image_ids[1]); | 37 top_arrow = *rb.GetImageSkiaNamed(arrow_image_ids[1]); |
| 65 right_arrow = *rb.GetImageSkiaNamed(arrow_image_ids[2]); | 38 right_arrow = *rb.GetImageSkiaNamed(arrow_image_ids[2]); |
| 66 bottom_arrow = *rb.GetImageSkiaNamed(arrow_image_ids[3]); | 39 bottom_arrow = *rb.GetImageSkiaNamed(arrow_image_ids[3]); |
| 67 arrow_thickness = top_arrow.height(); | 40 arrow_thickness = top_arrow.height(); |
| 68 } | 41 } |
| 69 } | 42 } |
| 70 | 43 |
| 44 BorderImages::~BorderImages() {} |
| 45 |
| 71 } // namespace internal | 46 } // namespace internal |
| 72 | 47 |
| 73 namespace { | 48 namespace { |
| 74 | 49 |
| 75 // The border and arrow stroke size used in image assets, in pixels. | |
| 76 const int kStroke = 1; | |
| 77 | |
| 78 // Bubble border and arrow image resource ids. They don't use the IMAGE_GRID | 50 // Bubble border and arrow image resource ids. They don't use the IMAGE_GRID |
| 79 // macro because there is no center image. | 51 // macro because there is no center image. |
| 80 const int kNoShadowImages[] = { | 52 const int kNoShadowImages[] = { |
| 81 IDR_BUBBLE_TL, IDR_BUBBLE_T, IDR_BUBBLE_TR, | 53 IDR_BUBBLE_TL, IDR_BUBBLE_T, IDR_BUBBLE_TR, |
| 82 IDR_BUBBLE_L, 0, IDR_BUBBLE_R, | 54 IDR_BUBBLE_L, 0, IDR_BUBBLE_R, |
| 83 IDR_BUBBLE_BL, IDR_BUBBLE_B, IDR_BUBBLE_BR }; | 55 IDR_BUBBLE_BL, IDR_BUBBLE_B, IDR_BUBBLE_BR }; |
| 84 const int kNoShadowArrows[] = { | 56 const int kNoShadowArrows[] = { |
| 85 IDR_BUBBLE_L_ARROW, IDR_BUBBLE_T_ARROW, | 57 IDR_BUBBLE_L_ARROW, IDR_BUBBLE_T_ARROW, |
| 86 IDR_BUBBLE_R_ARROW, IDR_BUBBLE_B_ARROW, }; | 58 IDR_BUBBLE_R_ARROW, IDR_BUBBLE_B_ARROW, }; |
| 87 | 59 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 case BubbleBorder::SHADOW_COUNT: | 115 case BubbleBorder::SHADOW_COUNT: |
| 144 NOTREACHED(); | 116 NOTREACHED(); |
| 145 break; | 117 break; |
| 146 } | 118 } |
| 147 | 119 |
| 148 return set; | 120 return set; |
| 149 } | 121 } |
| 150 | 122 |
| 151 } // namespace | 123 } // namespace |
| 152 | 124 |
| 125 const int BubbleBorder::kStroke = 1; |
| 126 |
| 153 BubbleBorder::BubbleBorder(Arrow arrow, Shadow shadow, SkColor color) | 127 BubbleBorder::BubbleBorder(Arrow arrow, Shadow shadow, SkColor color) |
| 154 : arrow_(arrow), | 128 : arrow_(arrow), |
| 155 arrow_offset_(0), | 129 arrow_offset_(0), |
| 156 arrow_paint_type_(PAINT_NORMAL), | 130 arrow_paint_type_(PAINT_NORMAL), |
| 157 alignment_(ALIGN_ARROW_TO_MID_ANCHOR), | 131 alignment_(ALIGN_ARROW_TO_MID_ANCHOR), |
| 158 shadow_(shadow), | 132 shadow_(shadow), |
| 159 background_color_(color), | 133 background_color_(color), |
| 160 use_theme_background_color_(false) { | 134 use_theme_background_color_(false) { |
| 161 DCHECK(shadow < SHADOW_COUNT); | 135 DCHECK(shadow < SHADOW_COUNT); |
| 162 images_ = GetBorderImages(shadow); | 136 images_ = GetBorderImages(shadow); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 const gfx::Insets insets = GetInsets(); | 245 const gfx::Insets insets = GetInsets(); |
| 272 size.Enlarge(insets.width(), insets.height()); | 246 size.Enlarge(insets.width(), insets.height()); |
| 273 | 247 |
| 274 // Ensure the bubble is large enough to not overlap border and arrow images. | 248 // Ensure the bubble is large enough to not overlap border and arrow images. |
| 275 const int min = 2 * images_->border_thickness; | 249 const int min = 2 * images_->border_thickness; |
| 276 const int min_with_arrow_width = min + images_->top_arrow.width(); | 250 const int min_with_arrow_width = min + images_->top_arrow.width(); |
| 277 const int min_with_arrow_thickness = images_->border_thickness + | 251 const int min_with_arrow_thickness = images_->border_thickness + |
| 278 std::max(images_->arrow_thickness + images_->border_interior_thickness, | 252 std::max(images_->arrow_thickness + images_->border_interior_thickness, |
| 279 images_->border_thickness); | 253 images_->border_thickness); |
| 280 // Only take arrow image sizes into account when the bubble tip is shown. | 254 // Only take arrow image sizes into account when the bubble tip is shown. |
| 281 if (arrow_paint_type_ == PAINT_TRANSPARENT || !has_arrow(arrow_)) | 255 if (arrow_paint_type_ == PAINT_NONE || !has_arrow(arrow_)) |
| 282 size.SetToMax(gfx::Size(min, min)); | 256 size.SetToMax(gfx::Size(min, min)); |
| 283 else if (is_arrow_on_horizontal(arrow_)) | 257 else if (is_arrow_on_horizontal(arrow_)) |
| 284 size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness)); | 258 size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness)); |
| 285 else | 259 else |
| 286 size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width)); | 260 size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width)); |
| 287 return size; | 261 return size; |
| 288 } | 262 } |
| 289 | 263 |
| 290 gfx::ImageSkia* BubbleBorder::GetArrowImage() const { | 264 gfx::ImageSkia* BubbleBorder::GetArrowImage() const { |
| 291 if (!has_arrow(arrow_)) | 265 if (!has_arrow(arrow_)) |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 SkDoubleToScalar(tip_y + multiplier * offset_to_next_vertex)); | 327 SkDoubleToScalar(tip_y + multiplier * offset_to_next_vertex)); |
| 354 path.close(); | 328 path.close(); |
| 355 | 329 |
| 356 SkPaint paint; | 330 SkPaint paint; |
| 357 paint.setStyle(SkPaint::kFill_Style); | 331 paint.setStyle(SkPaint::kFill_Style); |
| 358 paint.setColor(background_color_); | 332 paint.setColor(background_color_); |
| 359 | 333 |
| 360 canvas->DrawPath(path, paint); | 334 canvas->DrawPath(path, paint); |
| 361 } | 335 } |
| 362 | 336 |
| 337 internal::BorderImages* BubbleBorder::GetImagesForTest() const { |
| 338 return images_; |
| 339 } |
| 340 |
| 363 void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { | 341 void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { |
| 364 if (border_->shadow() == BubbleBorder::NO_SHADOW_OPAQUE_BORDER) | 342 if (border_->shadow() == BubbleBorder::NO_SHADOW_OPAQUE_BORDER) |
| 365 canvas->DrawColor(border_->background_color()); | 343 canvas->DrawColor(border_->background_color()); |
| 366 | 344 |
| 367 // Fill the contents with a round-rect region to match the border images. | 345 // Fill the contents with a round-rect region to match the border images. |
| 368 SkPaint paint; | 346 SkPaint paint; |
| 369 paint.setAntiAlias(true); | 347 paint.setAntiAlias(true); |
| 370 paint.setStyle(SkPaint::kFill_Style); | 348 paint.setStyle(SkPaint::kFill_Style); |
| 371 paint.setColor(border_->background_color()); | 349 paint.setColor(border_->background_color()); |
| 372 SkPath path; | 350 SkPath path; |
| 373 gfx::Rect bounds(view->GetLocalBounds()); | 351 gfx::Rect bounds(view->GetLocalBounds()); |
| 374 bounds.Inset(border_->GetInsets()); | 352 bounds.Inset(border_->GetInsets()); |
| 375 | 353 |
| 376 SkScalar radius = SkIntToScalar(border_->GetBorderCornerRadius()); | 354 SkScalar radius = SkIntToScalar(border_->GetBorderCornerRadius()); |
| 377 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius); | 355 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius); |
| 378 canvas->DrawPath(path, paint); | 356 canvas->DrawPath(path, paint); |
| 379 } | 357 } |
| 380 | 358 |
| 381 } // namespace views | 359 } // namespace views |
| OLD | NEW |