Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: ui/views/bubble/bubble_border.cc

Issue 10905311: Consolidate bubble border code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix nit in #2 and arrow interior color Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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> // for std::max 7 #include <algorithm> // for std::max
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "grit/ui_resources.h" 10 #include "grit/ui_resources.h"
(...skipping 11 matching lines...) Expand all
22 top(NULL), 22 top(NULL),
23 top_right(NULL), 23 top_right(NULL),
24 right(NULL), 24 right(NULL),
25 bottom_right(NULL), 25 bottom_right(NULL),
26 bottom(NULL), 26 bottom(NULL),
27 bottom_left(NULL), 27 bottom_left(NULL),
28 left_arrow(NULL), 28 left_arrow(NULL),
29 top_arrow(NULL), 29 top_arrow(NULL),
30 right_arrow(NULL), 30 right_arrow(NULL),
31 bottom_arrow(NULL), 31 bottom_arrow(NULL),
32 border_thickness(0) { 32 left_border_padding(0),
33 top_border_padding(0),
34 right_border_padding(0),
35 bottom_border_padding(0),
36 arrow_interior_height(0),
37 border_thickness(0),
38 corner_radius(0) {
33 } 39 }
34 40
35 gfx::ImageSkia* left; 41 gfx::ImageSkia* left;
36 gfx::ImageSkia* top_left; 42 gfx::ImageSkia* top_left;
37 gfx::ImageSkia* top; 43 gfx::ImageSkia* top;
38 gfx::ImageSkia* top_right; 44 gfx::ImageSkia* top_right;
39 gfx::ImageSkia* right; 45 gfx::ImageSkia* right;
40 gfx::ImageSkia* bottom_right; 46 gfx::ImageSkia* bottom_right;
41 gfx::ImageSkia* bottom; 47 gfx::ImageSkia* bottom;
42 gfx::ImageSkia* bottom_left; 48 gfx::ImageSkia* bottom_left;
49
43 gfx::ImageSkia* left_arrow; 50 gfx::ImageSkia* left_arrow;
44 gfx::ImageSkia* top_arrow; 51 gfx::ImageSkia* top_arrow;
45 gfx::ImageSkia* right_arrow; 52 gfx::ImageSkia* right_arrow;
46 gfx::ImageSkia* bottom_arrow; 53 gfx::ImageSkia* bottom_arrow;
54
55 // Offsets of where arrow tip pixel is in corresponding image assets.
msw 2012/09/18 19:33:42 nit: consider "Location of the arrow tip pixels in
xiyuan 2012/09/19 18:20:09 Done.
56 gfx::Point left_arrow_tip;
msw 2012/09/18 19:33:42 We can derive the tip position from the image and
xiyuan 2012/09/19 18:20:09 Done.
57 gfx::Point top_arrow_tip;
58 gfx::Point right_arrow_tip;
59 gfx::Point bottom_arrow_tip;
60
61 // Padding pixels between border pixels and image bounds.
62 int left_border_padding;
msw 2012/09/18 19:33:42 We can derive the image padding from the image and
xiyuan 2012/09/19 18:20:09 Done.
63 int top_border_padding;
64 int right_border_padding;
65 int bottom_border_padding;
66
67 int arrow_interior_height; // The height inside the arrow image, in pixels.
47 int border_thickness; 68 int border_thickness;
69 int corner_radius;
48 }; 70 };
49 71
50 // static 72 // static
51 struct BubbleBorder::BorderImages* BubbleBorder::normal_images_ = NULL; 73 struct BubbleBorder::BorderImages*
52 struct BubbleBorder::BorderImages* BubbleBorder::shadow_images_ = NULL; 74 BubbleBorder::border_images_[SHADOW_COUNT] = { NULL };
53
54 // The height inside the arrow image, in pixels.
55 static const int kArrowInteriorHeight = 7;
56 75
57 BubbleBorder::BubbleBorder(ArrowLocation arrow_location, Shadow shadow) 76 BubbleBorder::BubbleBorder(ArrowLocation arrow_location, Shadow shadow)
58 : override_arrow_offset_(0), 77 : override_arrow_offset_(0),
78 relative_arrow_offset_(0),
59 arrow_location_(arrow_location), 79 arrow_location_(arrow_location),
60 alignment_(ALIGN_ARROW_TO_MID_ANCHOR), 80 alignment_(ALIGN_ARROW_TO_MID_ANCHOR),
61 background_color_(SK_ColorWHITE) { 81 background_color_(SK_ColorWHITE),
82 center_arrow_(false) {
83 DCHECK(shadow < SHADOW_COUNT);
62 images_ = GetBorderImages(shadow); 84 images_ = GetBorderImages(shadow);
63 85
64 // Calculate horizontal and vertical insets for arrow by ensuring that 86 // Calculate horizontal and vertical insets for arrow by ensuring that
msw 2012/09/18 19:33:42 Should this be moved into CalculateArrowOffset?
xiyuan 2012/09/19 18:20:09 |arrow_offset_| is needed to get minimum bubble si
msw 2012/09/19 20:12:31 ok.
65 // the widest arrow and corner images will have enough room to avoid overlap 87 // the widest arrow and corner images will have enough room to avoid overlap
66 int offset_x = 88 int offset_x =
67 (std::max(images_->top_arrow->width(), 89 std::max(std::max(images_->top_arrow_tip.x(),
msw 2012/09/18 19:33:42 It seems like you could assume that the arrow imag
xiyuan 2012/09/19 18:20:09 Done.
68 images_->bottom_arrow->width()) / 2) + 90 images_->top_arrow->width() -
91 images_->top_arrow_tip.x()),
92 std::max(images_->bottom_arrow_tip.x(),
93 images_->bottom_arrow->width() -
94 images_->bottom_arrow_tip.x())) +
69 std::max(std::max(images_->top_left->width(), 95 std::max(std::max(images_->top_left->width(),
70 images_->top_right->width()), 96 images_->top_right->width()),
71 std::max(images_->bottom_left->width(), 97 std::max(images_->bottom_left->width(),
72 images_->bottom_right->width())); 98 images_->bottom_right->width()));
73 int offset_y = 99 int offset_y =
74 (std::max(images_->left_arrow->height(), 100 std::max(std::max(images_->left_arrow_tip.y(),
75 images_->right_arrow->height()) / 2) + 101 images_->left_arrow->height() -
102 images_->left_arrow_tip.y()),
103 std::max(images_->right_arrow_tip.y(),
104 images_->right_arrow->height() -
105 images_->right_arrow_tip.y())) +
76 std::max(std::max(images_->top_left->height(), 106 std::max(std::max(images_->top_left->height(),
77 images_->top_right->height()), 107 images_->top_right->height()),
78 std::max(images_->bottom_left->height(), 108 std::max(images_->bottom_left->height(),
79 images_->bottom_right->height())); 109 images_->bottom_right->height()));
80 arrow_offset_ = std::max(offset_x, offset_y); 110 arrow_offset_ = std::max(offset_x, offset_y);
81 } 111 }
82 112
83 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to, 113 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to,
84 const gfx::Size& contents_size) const { 114 const gfx::Size& contents_size) const {
85 // Desired size is size of contents enlarged by the size of the border images. 115 // Desired size is size of contents enlarged by the size of the border images.
86 gfx::Size border_size(contents_size); 116 gfx::Size border_size(contents_size);
87 gfx::Insets insets; 117 gfx::Insets insets;
88 GetInsets(&insets); 118 GetInsets(&insets);
89 border_size.Enlarge(insets.width(), insets.height()); 119 border_size.Enlarge(insets.width(), insets.height());
90 120
91 // Ensure the bubble has a minimum size that draws arrows correctly. 121 // Ensure the bubble has a minimum size that draws arrows correctly.
92 if (is_arrow_on_horizontal(arrow_location_)) 122 if (is_arrow_on_horizontal(arrow_location_))
93 border_size.set_width(std::max(border_size.width(), 2 * arrow_offset_)); 123 border_size.set_width(std::max(border_size.width(), 2 * arrow_offset_));
94 else if (has_arrow(arrow_location_)) 124 else if (has_arrow(arrow_location_))
95 border_size.set_height(std::max(border_size.height(), 2 * arrow_offset_)); 125 border_size.set_height(std::max(border_size.height(), 2 * arrow_offset_));
96 126
97 // Screen position depends on the arrow location. 127 // Screen position depends on the arrow location.
98 // The arrow should overlap the target by some amount since there is space 128 // The bubble should overlap the target by some amount since there is space
99 // for shadow between arrow tip and image bounds. 129 // for shadow between arrow tip/bubble border and image bounds.
100 const int kArrowOverlap = 3;
101 int x = position_relative_to.x(); 130 int x = position_relative_to.x();
102 int y = position_relative_to.y(); 131 int y = position_relative_to.y();
103 int w = position_relative_to.width(); 132 int w = position_relative_to.width();
104 int h = position_relative_to.height(); 133 int h = position_relative_to.height();
105 int arrow_offset = override_arrow_offset_ ? override_arrow_offset_ : 134
106 arrow_offset_; 135 const int arrow_offset = CalculateArrowOffset(border_size);
107 136
108 // Calculate bubble x coordinate. 137 // Calculate bubble x coordinate.
109 switch (arrow_location_) { 138 switch (arrow_location_) {
110 case TOP_LEFT: 139 case TOP_LEFT:
111 case BOTTOM_LEFT: 140 case BOTTOM_LEFT:
112 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? w / 2 - arrow_offset : 141 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? w / 2 - arrow_offset :
113 -kArrowOverlap; 142 -images_->left_border_padding;
114 break; 143 break;
115 144
116 case TOP_RIGHT: 145 case TOP_RIGHT:
117 case BOTTOM_RIGHT: 146 case BOTTOM_RIGHT:
118 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? 147 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ?
119 w / 2 + arrow_offset - border_size.width() + 1 : 148 w / 2 + arrow_offset - border_size.width() + 1 :
120 w - border_size.width() + kArrowOverlap; 149 w - border_size.width() + images_->right_border_padding;
121 break; 150 break;
122 151
123 case LEFT_TOP: 152 case LEFT_TOP:
124 case LEFT_BOTTOM: 153 case LEFT_BOTTOM:
125 x += w - kArrowOverlap; 154 x += w - images_->left_arrow_tip.x();
126 break; 155 break;
127 156
128 case RIGHT_TOP: 157 case RIGHT_TOP:
129 case RIGHT_BOTTOM: 158 case RIGHT_BOTTOM:
130 x += kArrowOverlap - border_size.width(); 159 x += images_->right_arrow->width() - images_->right_arrow_tip.x() -
160 border_size.width();
131 break; 161 break;
132 162
133 case NONE: 163 case NONE:
134 case FLOAT: 164 case FLOAT:
135 x += w / 2 - border_size.width() / 2; 165 x += w / 2 - border_size.width() / 2;
136 break; 166 break;
137 } 167 }
138 168
139 // Calculate bubble y coordinate. 169 // Calculate bubble y coordinate.
140 switch (arrow_location_) { 170 switch (arrow_location_) {
141 case TOP_LEFT: 171 case TOP_LEFT:
142 case TOP_RIGHT: 172 case TOP_RIGHT:
143 y += h - kArrowOverlap; 173 y += h - images_->top_arrow_tip.y();
144 break; 174 break;
145 175
146 case BOTTOM_LEFT: 176 case BOTTOM_LEFT:
147 case BOTTOM_RIGHT: 177 case BOTTOM_RIGHT:
148 y += kArrowOverlap - border_size.height(); 178 y += images_->bottom_arrow->height() - images_->bottom_arrow_tip.y() -
179 border_size.height();
149 break; 180 break;
150 181
151 case LEFT_TOP: 182 case LEFT_TOP:
152 case RIGHT_TOP: 183 case RIGHT_TOP:
153 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? h / 2 - arrow_offset : 184 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? h / 2 - arrow_offset :
154 -kArrowOverlap; 185 -images_->top_border_padding;
155 break; 186 break;
156 187
157 case LEFT_BOTTOM: 188 case LEFT_BOTTOM:
158 case RIGHT_BOTTOM: 189 case RIGHT_BOTTOM:
159 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? 190 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ?
160 h / 2 + arrow_offset - border_size.height() + 1 : 191 h / 2 + arrow_offset - border_size.height() + 1 :
161 h - border_size.height() + kArrowOverlap; 192 h - border_size.height() + images_->bottom_border_padding;
162 break; 193 break;
163 194
164 case NONE: 195 case NONE:
165 y += h; 196 y += h;
166 break; 197 break;
167 198
168 case FLOAT: 199 case FLOAT:
169 y += h / 2 - border_size.height() / 2; 200 y += h / 2 - border_size.height() / 2;
170 break; 201 break;
171 } 202 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 // Nothing to do. 240 // Nothing to do.
210 break; 241 break;
211 } 242 }
212 insets->Set(top, left, bottom, right); 243 insets->Set(top, left, bottom, right);
213 } 244 }
214 245
215 int BubbleBorder::GetBorderThickness() const { 246 int BubbleBorder::GetBorderThickness() const {
216 return images_->border_thickness; 247 return images_->border_thickness;
217 } 248 }
218 249
250 int BubbleBorder::GetBorderCornerRadius() const {
251 return images_->corner_radius;
252 }
253
219 int BubbleBorder::SetArrowOffset(int offset, const gfx::Size& contents_size) { 254 int BubbleBorder::SetArrowOffset(int offset, const gfx::Size& contents_size) {
220 gfx::Size border_size(contents_size); 255 gfx::Size border_size(contents_size);
221 gfx::Insets insets; 256 gfx::Insets insets;
222 GetInsets(&insets); 257 GetInsets(&insets);
223 border_size.Enlarge(insets.left() + insets.right(), 258 border_size.Enlarge(insets.left() + insets.right(),
224 insets.top() + insets.bottom()); 259 insets.top() + insets.bottom());
225 offset = std::max(arrow_offset_, 260 offset = SanitizeArrowOffset(offset, border_size);
msw 2012/09/18 19:33:42 Nix this, its redundant with the call in Calculate
xiyuan 2012/09/19 18:20:09 Done. And made SetArrowOffset an inline accessor.
msw 2012/09/19 20:12:31 Nice.
226 std::min(offset, (is_arrow_on_horizontal(arrow_location_) ?
227 border_size.width() : border_size.height()) - arrow_offset_));
228 override_arrow_offset_ = offset; 261 override_arrow_offset_ = offset;
229 return override_arrow_offset_; 262 return override_arrow_offset_;
230 } 263 }
231 264
232 // static 265 // static
233 BubbleBorder::BorderImages* BubbleBorder::GetBorderImages(Shadow shadow) { 266 BubbleBorder::BorderImages* BubbleBorder::GetBorderImages(Shadow shadow) {
234 if (shadow == SHADOW && shadow_images_ == NULL) { 267 DCHECK(shadow < SHADOW_COUNT);
268
269 struct BorderImages*& images = border_images_[shadow];
270 if (images == NULL) {
msw 2012/09/18 19:33:42 Can you invert this check to make it an early retu
xiyuan 2012/09/19 18:20:09 Done.
271 images = new BorderImages();
272
235 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 273 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
236 shadow_images_ = new BorderImages(); 274 switch (shadow) {
msw 2012/09/18 19:33:42 This is getting unwieldy, perhaps BorderImages nee
xiyuan 2012/09/19 18:20:09 Done. Added IDR arrays and pass it to BorderImage'
msw 2012/09/19 20:12:31 All excellent (though GetImageSkiaNamed was probab
237 shadow_images_->left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_L); 275 case SHADOW:
238 shadow_images_->top_left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_TL); 276 images->left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_L);
239 shadow_images_->top = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_T); 277 images->top_left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_TL);
240 shadow_images_->top_right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_TR); 278 images->top = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_T);
241 shadow_images_->right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_R); 279 images->top_right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_TR);
242 shadow_images_->bottom_right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_BR); 280 images->right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_R);
243 shadow_images_->bottom = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_B); 281 images->bottom_right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_BR);
244 shadow_images_->bottom_left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_BL); 282 images->bottom = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_B);
245 shadow_images_->left_arrow = new gfx::ImageSkia(); 283 images->bottom_left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_BL);
246 shadow_images_->top_arrow = new gfx::ImageSkia(); 284 images->left_arrow = new gfx::ImageSkia();
msw 2012/09/18 19:33:42 These seem to be leaked (prior to this CL, not you
xiyuan 2012/09/19 18:20:09 Resolved as we use ImageSkia object instead of poi
msw 2012/09/19 20:12:31 Great!
247 shadow_images_->right_arrow = new gfx::ImageSkia(); 285 images->top_arrow = new gfx::ImageSkia();
248 shadow_images_->bottom_arrow = new gfx::ImageSkia(); 286 images->right_arrow = new gfx::ImageSkia();
249 shadow_images_->border_thickness = 10; 287 images->bottom_arrow = new gfx::ImageSkia();
250 } else if (shadow == NO_SHADOW && normal_images_ == NULL) { 288 images->arrow_interior_height = 7;
msw 2012/09/18 19:33:42 This group has no arrow, why is arrow_interior_hei
xiyuan 2012/09/19 18:20:09 Removed since it's not used and we should be okay
251 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 289 images->border_thickness = 10;
252 normal_images_ = new BorderImages(); 290 images->corner_radius = 4;
253 normal_images_->left = rb.GetImageSkiaNamed(IDR_BUBBLE_L); 291 break;
254 normal_images_->top_left = rb.GetImageSkiaNamed(IDR_BUBBLE_TL); 292 case NO_SHADOW:
255 normal_images_->top = rb.GetImageSkiaNamed(IDR_BUBBLE_T); 293 images->left = rb.GetImageSkiaNamed(IDR_BUBBLE_L);
256 normal_images_->top_right = rb.GetImageSkiaNamed(IDR_BUBBLE_TR); 294 images->top_left = rb.GetImageSkiaNamed(IDR_BUBBLE_TL);
257 normal_images_->right = rb.GetImageSkiaNamed(IDR_BUBBLE_R); 295 images->top = rb.GetImageSkiaNamed(IDR_BUBBLE_T);
258 normal_images_->bottom_right = rb.GetImageSkiaNamed(IDR_BUBBLE_BR); 296 images->top_right = rb.GetImageSkiaNamed(IDR_BUBBLE_TR);
259 normal_images_->bottom = rb.GetImageSkiaNamed(IDR_BUBBLE_B); 297 images->right = rb.GetImageSkiaNamed(IDR_BUBBLE_R);
260 normal_images_->bottom_left = rb.GetImageSkiaNamed(IDR_BUBBLE_BL); 298 images->bottom_right = rb.GetImageSkiaNamed(IDR_BUBBLE_BR);
261 normal_images_->left_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_L_ARROW); 299 images->bottom = rb.GetImageSkiaNamed(IDR_BUBBLE_B);
262 normal_images_->top_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_T_ARROW); 300 images->bottom_left = rb.GetImageSkiaNamed(IDR_BUBBLE_BL);
263 normal_images_->right_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_R_ARROW); 301 images->left_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_L_ARROW);
264 normal_images_->bottom_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_B_ARROW); 302 images->top_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_T_ARROW);
265 normal_images_->border_thickness = 0; 303 images->right_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_R_ARROW);
304 images->bottom_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_B_ARROW);
305 images->left_arrow_tip = gfx::Point(3, 11);
306 images->top_arrow_tip = gfx::Point(9, 3);
307 images->right_arrow_tip = gfx::Point(9, 11);
308 images->bottom_arrow_tip = gfx::Point(9, 9);
309 images->left_border_padding = 3;
310 images->top_border_padding = 1;
311 images->right_border_padding = 3;
312 images->bottom_border_padding = 5;
313 images->arrow_interior_height = 7;
314 images->border_thickness = 0;
315 images->corner_radius = 4;
316 break;
317 #if defined(USE_AURA)
318 case BIG_SHADOW:
319 images->left =
320 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_BIG_LEFT);
321 images->top_left =
322 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP_LEFT);
323 images->top =
324 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP);
325 images->top_right =
326 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP_RIGHT);
327 images->right =
328 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_BIG_RIGHT);
329 images->bottom_right =
330 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM_RIGHT);
331 images->bottom =
332 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM);
333 images->bottom_left =
334 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM_LEFT);
335 images->left_arrow =
336 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_LEFT);
337 images->top_arrow =
338 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_TOP);
339 images->right_arrow =
340 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_RIGHT);
341 images->bottom_arrow =
342 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_BOTTOM);
343 images->left_arrow_tip = gfx::Point(20, 16);
344 images->top_arrow_tip = gfx::Point(21, 20);
345 images->right_arrow_tip = gfx::Point(10, 16);
346 images->bottom_arrow_tip = gfx::Point(21, 10);
347 images->left_border_padding = 30;
348 images->top_border_padding = 30;
349 images->right_border_padding = 30;
350 images->bottom_border_padding = 30;
351 images->arrow_interior_height = 9;
352 images->border_thickness = 0;
353 images->corner_radius = 3;
354 break;
355 case SMALL_SHADOW:
356 images->left =
357 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_LEFT);
358 images->top_left =
359 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_LEFT);
360 images->top =
361 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP);
362 images->top_right =
363 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_RIGHT);
364 images->right =
365 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_RIGHT);
366 images->bottom_right =
367 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_RIGHT);
368 images->bottom =
369 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM);
370 images->bottom_left =
371 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_LEFT);
372 images->left_arrow =
373 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_LEFT);
374 images->top_arrow =
375 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_TOP);
376 images->right_arrow =
377 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_RIGHT);
378 images->bottom_arrow =
379 rb.GetImageSkiaNamed(IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_BOTTOM);
380 images->left_arrow_tip = gfx::Point(5, 9);
381 images->top_arrow_tip = gfx::Point(12, 5);
382 images->right_arrow_tip = gfx::Point(10, 9);
383 images->bottom_arrow_tip = gfx::Point(12, 10);
384 images->left_border_padding = 15;
385 images->top_border_padding = 15;
386 images->right_border_padding = 15;
387 images->bottom_border_padding = 15;
388 images->arrow_interior_height = 9;
389 images->border_thickness = 0;
390 images->corner_radius = 3;
391 break;
392 #endif
393 case SHADOW_COUNT:
msw 2012/09/18 19:33:42 Make this (or add a similar) default: case.
xiyuan 2012/09/19 18:20:09 Done. I found not using "default" for enum based
msw 2012/09/19 20:12:31 Good point, feel free to switch it back; thanks fo
394 NOTREACHED();
395 break;
396 }
266 } 397 }
267 return shadow == SHADOW ? shadow_images_ : normal_images_; 398
399 return images;
268 } 400 }
269 401
270 BubbleBorder::~BubbleBorder() {} 402 BubbleBorder::~BubbleBorder() {}
271 403
272 void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { 404 void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
273 // Convenience shorthand variables. 405 // Convenience shorthand variables.
274 const int tl_width = images_->top_left->width(); 406 const int tl_width = images_->top_left->width();
275 const int tl_height = images_->top_left->height(); 407 const int tl_height = images_->top_left->height();
276 const int t_height = images_->top->height(); 408 const int t_height = images_->top->height();
277 const int tr_width = images_->top_right->width(); 409 const int tr_width = images_->top_right->width();
278 const int tr_height = images_->top_right->height(); 410 const int tr_height = images_->top_right->height();
279 const int l_width = images_->left->width(); 411 const int l_width = images_->left->width();
280 const int r_width = images_->right->width(); 412 const int r_width = images_->right->width();
281 const int br_width = images_->bottom_right->width(); 413 const int br_width = images_->bottom_right->width();
282 const int br_height = images_->bottom_right->height(); 414 const int br_height = images_->bottom_right->height();
283 const int b_height = images_->bottom->height(); 415 const int b_height = images_->bottom->height();
284 const int bl_width = images_->bottom_left->width(); 416 const int bl_width = images_->bottom_left->width();
285 const int bl_height = images_->bottom_left->height(); 417 const int bl_height = images_->bottom_left->height();
286 418
287 gfx::Insets insets; 419 gfx::Insets insets;
288 GetInsets(&insets); 420 GetInsets(&insets);
289 const int top = insets.top() - t_height; 421 const int top = insets.top() - t_height;
290 const int bottom = view.height() - insets.bottom() + b_height; 422 const int bottom = view.height() - insets.bottom() + b_height;
291 const int left = insets.left() - l_width; 423 const int left = insets.left() - l_width;
292 const int right = view.width() - insets.right() + r_width; 424 const int right = view.width() - insets.right() + r_width;
293 const int height = bottom - top; 425 const int height = bottom - top;
294 const int width = right - left; 426 const int width = right - left;
295 427
296 // |arrow_offset| is offset of arrow from the begining of the edge. 428 // |arrow_offset| is offset of arrow from the beginning of the edge.
297 int arrow_offset = arrow_offset_; 429 int arrow_offset = CalculateArrowOffset(view.size());
298 if (override_arrow_offset_) 430 if (is_arrow_on_horizontal(arrow_location_) &&
299 arrow_offset = override_arrow_offset_; 431 !is_arrow_on_left(arrow_location_)) {
300 else if (is_arrow_on_horizontal(arrow_location_) &&
301 !is_arrow_on_left(arrow_location_)) {
302 arrow_offset = view.width() - arrow_offset - 1; 432 arrow_offset = view.width() - arrow_offset - 1;
303 } else if (!is_arrow_on_horizontal(arrow_location_) && 433 } else if (!is_arrow_on_horizontal(arrow_location_) &&
304 !is_arrow_on_top(arrow_location_)) { 434 !is_arrow_on_top(arrow_location_)) {
305 arrow_offset = view.height() - arrow_offset - 1; 435 arrow_offset = view.height() - arrow_offset - 1;
306 } 436 }
307 437
308 // Left edge. 438 // Left edge.
309 if (arrow_location_ == LEFT_TOP || arrow_location_ == LEFT_BOTTOM) { 439 if (arrow_location_ == LEFT_TOP || arrow_location_ == LEFT_BOTTOM) {
310 int start_y = top + tl_height; 440 int start_y = top + tl_height;
311 int before_arrow = 441 int before_arrow =
312 arrow_offset - start_y - images_->left_arrow->height() / 2; 442 arrow_offset - start_y - images_->left_arrow_tip.y();
313 int after_arrow = height - tl_height - bl_height - 443 int after_arrow = height - tl_height - bl_height -
314 images_->left_arrow->height() - before_arrow; 444 images_->left_arrow->height() - before_arrow;
315 // Shift tip coordinates half pixel so that skia draws the tip correctly. 445 // Shift tip coordinates half pixel so that skia draws the tip correctly.
316 DrawArrowInterior(canvas, 446 DrawArrowInterior(canvas,
317 images_->left_arrow->width() - kArrowInteriorHeight - 0.5f, 447 images_->left_arrow->width() - images_->arrow_interior_height - 0.5f,
318 start_y + before_arrow + images_->left_arrow->height() / 2 - 0.5f); 448 start_y + before_arrow + images_->left_arrow_tip.y() - 0.5f);
319 DrawEdgeWithArrow(canvas, 449 DrawEdgeWithArrow(canvas,
320 false, 450 false,
321 images_->left, 451 images_->left,
322 images_->left_arrow, 452 images_->left_arrow,
323 left, 453 left,
324 start_y, 454 start_y,
325 before_arrow, 455 before_arrow,
326 after_arrow, 456 after_arrow,
327 images_->left->width() - images_->left_arrow->width()); 457 images_->left->width() - images_->left_arrow->width());
328 } else { 458 } else {
329 canvas->TileImageInt(*images_->left, left, top + tl_height, l_width, 459 canvas->TileImageInt(*images_->left, left, top + tl_height, l_width,
330 height - tl_height - bl_height); 460 height - tl_height - bl_height);
331 } 461 }
332 462
333 // Top left corner. 463 // Top left corner.
334 canvas->DrawImageInt(*images_->top_left, left, top); 464 canvas->DrawImageInt(*images_->top_left, left, top);
335 465
336 // Top edge. 466 // Top edge.
337 if (arrow_location_ == TOP_LEFT || arrow_location_ == TOP_RIGHT) { 467 if (arrow_location_ == TOP_LEFT || arrow_location_ == TOP_RIGHT) {
338 int start_x = left + tl_width; 468 int start_x = left + tl_width;
339 int before_arrow = arrow_offset - start_x - images_->top_arrow->width() / 2; 469 int before_arrow = arrow_offset - start_x - images_->top_arrow_tip.x();
340 int after_arrow = width - tl_width - tr_width - 470 int after_arrow = width - tl_width - tr_width -
341 images_->top_arrow->width() - before_arrow; 471 images_->top_arrow->width() - before_arrow;
342 DrawArrowInterior(canvas, 472 DrawArrowInterior(canvas,
343 start_x + before_arrow + images_->top_arrow->width() / 2, 473 start_x + before_arrow + images_->top_arrow_tip.x(),
344 images_->top_arrow->height() - kArrowInteriorHeight); 474 images_->top_arrow->height() - images_->arrow_interior_height);
345 DrawEdgeWithArrow(canvas, 475 DrawEdgeWithArrow(canvas,
346 true, 476 true,
347 images_->top, 477 images_->top,
348 images_->top_arrow, 478 images_->top_arrow,
349 start_x, 479 start_x,
350 top, 480 top,
351 before_arrow, 481 before_arrow,
352 after_arrow, 482 after_arrow,
353 images_->top->height() - images_->top_arrow->height()); 483 images_->top->height() - images_->top_arrow->height());
354 } else { 484 } else {
355 canvas->TileImageInt(*images_->top, left + tl_width, top, 485 canvas->TileImageInt(*images_->top, left + tl_width, top,
356 width - tl_width - tr_width, t_height); 486 width - tl_width - tr_width, t_height);
357 } 487 }
358 488
359 // Top right corner. 489 // Top right corner.
360 canvas->DrawImageInt(*images_->top_right, right - tr_width, top); 490 canvas->DrawImageInt(*images_->top_right, right - tr_width, top);
361 491
362 // Right edge. 492 // Right edge.
363 if (arrow_location_ == RIGHT_TOP || arrow_location_ == RIGHT_BOTTOM) { 493 if (arrow_location_ == RIGHT_TOP || arrow_location_ == RIGHT_BOTTOM) {
364 int start_y = top + tr_height; 494 int start_y = top + tr_height;
365 int before_arrow = 495 int before_arrow =
366 arrow_offset - start_y - images_->right_arrow->height() / 2; 496 arrow_offset - start_y - images_->right_arrow_tip.y();
367 int after_arrow = height - tl_height - bl_height - 497 int after_arrow = height - tl_height - bl_height -
368 images_->right_arrow->height() - before_arrow; 498 images_->right_arrow->height() - before_arrow;
369 // Shift tip coordinates half pixel so that skia draws the tip correctly. 499 // Shift tip coordinates half pixel so that skia draws the tip correctly.
370 DrawArrowInterior(canvas, 500 DrawArrowInterior(canvas,
371 right - r_width + kArrowInteriorHeight - 0.5f, 501 right - r_width + images_->arrow_interior_height - 0.5f,
372 start_y + before_arrow + images_->right_arrow->height() / 2 - 0.5f); 502 start_y + before_arrow + images_->right_arrow_tip.y() - 0.5f);
373 DrawEdgeWithArrow(canvas, 503 DrawEdgeWithArrow(canvas,
374 false, 504 false,
375 images_->right, 505 images_->right,
376 images_->right_arrow, 506 images_->right_arrow,
377 right - r_width, 507 right - r_width,
378 start_y, 508 start_y,
379 before_arrow, 509 before_arrow,
380 after_arrow, 510 after_arrow,
381 0); 511 0);
382 } else { 512 } else {
383 canvas->TileImageInt(*images_->right, right - r_width, top + tr_height, 513 canvas->TileImageInt(*images_->right, right - r_width, top + tr_height,
384 r_width, height - tr_height - br_height); 514 r_width, height - tr_height - br_height);
385 } 515 }
386 516
387 // Bottom right corner. 517 // Bottom right corner.
388 canvas->DrawImageInt(*images_->bottom_right, 518 canvas->DrawImageInt(*images_->bottom_right,
389 right - br_width, 519 right - br_width,
390 bottom - br_height); 520 bottom - br_height);
391 521
392 // Bottom edge. 522 // Bottom edge.
393 if (arrow_location_ == BOTTOM_LEFT || arrow_location_ == BOTTOM_RIGHT) { 523 if (arrow_location_ == BOTTOM_LEFT || arrow_location_ == BOTTOM_RIGHT) {
394 int start_x = left + bl_width; 524 int start_x = left + bl_width;
395 int before_arrow = 525 int before_arrow =
396 arrow_offset - start_x - images_->bottom_arrow->width() / 2; 526 arrow_offset - start_x - images_->bottom_arrow_tip.x();
397 int after_arrow = width - bl_width - br_width - 527 int after_arrow = width - bl_width - br_width -
398 images_->bottom_arrow->width() - before_arrow; 528 images_->bottom_arrow->width() - before_arrow;
399 DrawArrowInterior(canvas, 529 DrawArrowInterior(canvas,
400 start_x + before_arrow + images_->bottom_arrow->width() / 2, 530 start_x + before_arrow + images_->bottom_arrow_tip.x(),
401 bottom - b_height + kArrowInteriorHeight); 531 bottom - b_height + images_->arrow_interior_height);
402 DrawEdgeWithArrow(canvas, 532 DrawEdgeWithArrow(canvas,
403 true, 533 true,
404 images_->bottom, 534 images_->bottom,
405 images_->bottom_arrow, 535 images_->bottom_arrow,
406 start_x, 536 start_x,
407 bottom - b_height, 537 bottom - b_height,
408 before_arrow, 538 before_arrow,
409 after_arrow, 539 after_arrow,
410 0); 540 0);
411 } else { 541 } else {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 } 586 }
457 } 587 }
458 588
459 void BubbleBorder::DrawArrowInterior(gfx::Canvas* canvas, 589 void BubbleBorder::DrawArrowInterior(gfx::Canvas* canvas,
460 float tip_x, 590 float tip_x,
461 float tip_y) const { 591 float tip_y) const {
462 const bool is_horizontal = is_arrow_on_horizontal(arrow_location_); 592 const bool is_horizontal = is_arrow_on_horizontal(arrow_location_);
463 const bool positive_offset = is_horizontal ? 593 const bool positive_offset = is_horizontal ?
464 is_arrow_on_top(arrow_location_) : is_arrow_on_left(arrow_location_); 594 is_arrow_on_top(arrow_location_) : is_arrow_on_left(arrow_location_);
465 const int offset_to_next_vertex = positive_offset ? 595 const int offset_to_next_vertex = positive_offset ?
466 kArrowInteriorHeight : -kArrowInteriorHeight; 596 images_->arrow_interior_height : -images_->arrow_interior_height;
467 597
468 SkPath path; 598 SkPath path;
469 path.incReserve(4); 599 path.incReserve(4);
470 path.moveTo(SkDoubleToScalar(tip_x), SkDoubleToScalar(tip_y)); 600 path.moveTo(SkDoubleToScalar(tip_x), SkDoubleToScalar(tip_y));
471 path.lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex), 601 path.lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex),
472 SkDoubleToScalar(tip_y + offset_to_next_vertex)); 602 SkDoubleToScalar(tip_y + offset_to_next_vertex));
473 if (is_horizontal) { 603 if (is_horizontal) {
474 path.lineTo(SkDoubleToScalar(tip_x - offset_to_next_vertex), 604 path.lineTo(SkDoubleToScalar(tip_x - offset_to_next_vertex),
475 SkDoubleToScalar(tip_y + offset_to_next_vertex)); 605 SkDoubleToScalar(tip_y + offset_to_next_vertex));
476 } else { 606 } else {
477 path.lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex), 607 path.lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex),
478 SkDoubleToScalar(tip_y - offset_to_next_vertex)); 608 SkDoubleToScalar(tip_y - offset_to_next_vertex));
479 } 609 }
480 path.close(); 610 path.close();
481 611
482 SkPaint paint; 612 SkPaint paint;
483 paint.setStyle(SkPaint::kFill_Style); 613 paint.setStyle(SkPaint::kFill_Style);
484 paint.setColor(background_color_); 614 paint.setColor(background_color_);
485 615
486 canvas->DrawPath(path, paint); 616 canvas->DrawPath(path, paint);
487 } 617 }
488 618
619 int BubbleBorder::SanitizeArrowOffset(int arrow_offset,
msw 2012/09/18 19:33:42 After removing the call in SetArrowOffset, inline
xiyuan 2012/09/19 18:20:09 Done.
620 const gfx::Size& border_size) const {
621 return std::max(arrow_offset_,
622 std::min(arrow_offset, (is_arrow_on_horizontal(arrow_location_) ?
623 border_size.width() : border_size.height()) - arrow_offset_));
624 }
625
626 int BubbleBorder::CalculateArrowOffset(const gfx::Size& border_size) const {
627 int arrow_offset = arrow_offset_;
628 if (override_arrow_offset_)
msw 2012/09/18 19:33:42 Add braces here to match the else case.
xiyuan 2012/09/19 18:20:09 Done.
629 arrow_offset = override_arrow_offset_;
630 else if (center_arrow_) {
631 if (is_arrow_on_horizontal(arrow_location_))
632 arrow_offset = border_size.width() / 2;
633 else if (has_arrow(arrow_location_))
634 arrow_offset = border_size.height() / 2;
635 }
636
637 arrow_offset += relative_arrow_offset_;
638 return SanitizeArrowOffset(arrow_offset, border_size);
639 }
640
489 ///////////////////////// 641 /////////////////////////
490 642
491 void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { 643 void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const {
492 // Clip out the client bounds to prevent overlapping transparent widgets. 644 // Clip out the client bounds to prevent overlapping transparent widgets.
493 if (!border_->client_bounds().IsEmpty()) { 645 if (!border_->client_bounds().IsEmpty()) {
494 SkRect client_rect(gfx::RectToSkRect(border_->client_bounds())); 646 SkRect client_rect(gfx::RectToSkRect(border_->client_bounds()));
495 canvas->sk_canvas()->clipRect(client_rect, SkRegion::kDifference_Op); 647 canvas->sk_canvas()->clipRect(client_rect, SkRegion::kDifference_Op);
496 } 648 }
497 649
498 // The border of this view creates an anti-aliased round-rect region for the 650 // The border of this view creates an anti-aliased round-rect region for the
499 // contents, which we need to fill with the background color. 651 // contents, which we need to fill with the background color.
500 // NOTE: This doesn't handle an arrow location of "NONE", which has square top 652 // NOTE: This doesn't handle an arrow location of "NONE", which has square top
501 // corners. 653 // corners.
502 SkPaint paint; 654 SkPaint paint;
503 paint.setAntiAlias(true); 655 paint.setAntiAlias(true);
504 paint.setStyle(SkPaint::kFill_Style); 656 paint.setStyle(SkPaint::kFill_Style);
505 paint.setColor(border_->background_color()); 657 paint.setColor(border_->background_color());
506 SkPath path; 658 SkPath path;
507 gfx::Rect bounds(view->GetContentsBounds()); 659 gfx::Rect bounds(view->GetContentsBounds());
508 bounds.Inset(-border_->GetBorderThickness(), -border_->GetBorderThickness()); 660 bounds.Inset(-border_->GetBorderThickness(), -border_->GetBorderThickness());
509 SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); 661 SkScalar radius = SkIntToScalar(border_->GetBorderCornerRadius());
510 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius); 662 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius);
511 canvas->DrawPath(path, paint); 663 canvas->DrawPath(path, paint);
512 } 664 }
513 665
514 } // namespace views 666 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698