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_; | |
msw
2014/08/23 00:29:12
nit: indent only 2 spaces.
bruthig
2014/08/25 14:47:28
Done.
| |
339 } | |
340 | |
363 void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { | 341 void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { |
msw
2014/08/23 00:29:12
optional nit: reorder this definition to match its
bruthig
2014/08/23 00:39:45
Not exactly sure what you mean here? This is the
msw
2014/08/23 00:59:22
Ah, my mistake, ignore that comment.
| |
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 |