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

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: remove USE_AURA ifdef for kBigShadowImages and kSmalleShadowImages 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
« no previous file with comments | « ui/views/bubble/bubble_border.h ('k') | ui/views/bubble/bubble_border_2.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "ui/base/resource/resource_bundle.h" 11 #include "ui/base/resource/resource_bundle.h"
12 #include "ui/gfx/canvas.h" 12 #include "ui/gfx/canvas.h"
13 #include "ui/gfx/image/image_skia.h" 13 #include "ui/gfx/image/image_skia.h"
14 #include "ui/gfx/skia_util.h" 14 #include "ui/gfx/skia_util.h"
15 15
16 namespace {
17
18 // Stroke size in pixels of borders in image assets.
19 const int kBorderStrokeSize = 1;
20
21 // Border image resource ids.
22 const int kShadowImages[] = {
23 IDR_BUBBLE_SHADOW_L,
24 IDR_BUBBLE_SHADOW_TL,
25 IDR_BUBBLE_SHADOW_T,
26 IDR_BUBBLE_SHADOW_TR,
27 IDR_BUBBLE_SHADOW_R,
28 IDR_BUBBLE_SHADOW_BR,
29 IDR_BUBBLE_SHADOW_B,
30 IDR_BUBBLE_SHADOW_BL,
31 };
32
33 const int kNoShadowImages[] = {
34 IDR_BUBBLE_L,
35 IDR_BUBBLE_TL,
36 IDR_BUBBLE_T,
37 IDR_BUBBLE_TR,
38 IDR_BUBBLE_R,
39 IDR_BUBBLE_BR,
40 IDR_BUBBLE_B,
41 IDR_BUBBLE_BL,
42 IDR_BUBBLE_L_ARROW,
43 IDR_BUBBLE_T_ARROW,
44 IDR_BUBBLE_R_ARROW,
45 IDR_BUBBLE_B_ARROW,
46 };
47
48 const int kBigShadowImages[] = {
49 IDR_WINDOW_BUBBLE_SHADOW_BIG_LEFT,
50 IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP_LEFT,
51 IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP,
52 IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP_RIGHT,
53 IDR_WINDOW_BUBBLE_SHADOW_BIG_RIGHT,
54 IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM_RIGHT,
55 IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM,
56 IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM_LEFT,
57 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_LEFT,
58 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_TOP,
59 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_RIGHT,
60 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_BOTTOM,
61 };
62
63 const int kSmallShadowImages[] = {
64 IDR_WINDOW_BUBBLE_SHADOW_SMALL_LEFT,
65 IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_LEFT,
66 IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP,
67 IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_RIGHT,
68 IDR_WINDOW_BUBBLE_SHADOW_SMALL_RIGHT,
69 IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_RIGHT,
70 IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM,
71 IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_LEFT,
72 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_LEFT,
73 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_TOP,
74 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_RIGHT,
75 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_BOTTOM,
76 };
77
78 } // namespace
79
16 namespace views { 80 namespace views {
17 81
18 struct BubbleBorder::BorderImages { 82 struct BubbleBorder::BorderImages {
19 BorderImages() 83 BorderImages(const int image_ids[],
20 : left(NULL), 84 size_t image_ids_size,
21 top_left(NULL), 85 int arrow_interior_height,
22 top(NULL), 86 int border_thickness,
23 top_right(NULL), 87 int corner_radius)
24 right(NULL), 88 : arrow_interior_height(arrow_interior_height),
25 bottom_right(NULL), 89 border_thickness(border_thickness),
26 bottom(NULL), 90 corner_radius(corner_radius) {
27 bottom_left(NULL), 91 // Only two possible sizes of image ids array.
28 left_arrow(NULL), 92 DCHECK(image_ids_size == 12 || image_ids_size == 8);
29 top_arrow(NULL), 93
30 right_arrow(NULL), 94 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
31 bottom_arrow(NULL), 95
32 border_thickness(0) { 96 left = *rb.GetImageSkiaNamed(image_ids[0]);
97 top_left = *rb.GetImageSkiaNamed(image_ids[1]);
98 top = *rb.GetImageSkiaNamed(image_ids[2]);
99 top_right = *rb.GetImageSkiaNamed(image_ids[3]);
100 right = *rb.GetImageSkiaNamed(image_ids[4]);
101 bottom_right = *rb.GetImageSkiaNamed(image_ids[5]);
102 bottom = *rb.GetImageSkiaNamed(image_ids[6]);
103 bottom_left = *rb.GetImageSkiaNamed(image_ids[7]);
104
105 if (image_ids_size > 8) {
106 left_arrow = *rb.GetImageSkiaNamed(image_ids[8]);
107 top_arrow = *rb.GetImageSkiaNamed(image_ids[9]);
108 right_arrow = *rb.GetImageSkiaNamed(image_ids[10]);
109 bottom_arrow = *rb.GetImageSkiaNamed(image_ids[11]);
110 }
33 } 111 }
34 112
35 gfx::ImageSkia* left; 113 gfx::ImageSkia left;
36 gfx::ImageSkia* top_left; 114 gfx::ImageSkia top_left;
37 gfx::ImageSkia* top; 115 gfx::ImageSkia top;
38 gfx::ImageSkia* top_right; 116 gfx::ImageSkia top_right;
39 gfx::ImageSkia* right; 117 gfx::ImageSkia right;
40 gfx::ImageSkia* bottom_right; 118 gfx::ImageSkia bottom_right;
41 gfx::ImageSkia* bottom; 119 gfx::ImageSkia bottom;
42 gfx::ImageSkia* bottom_left; 120 gfx::ImageSkia bottom_left;
43 gfx::ImageSkia* left_arrow; 121
44 gfx::ImageSkia* top_arrow; 122 gfx::ImageSkia left_arrow;
45 gfx::ImageSkia* right_arrow; 123 gfx::ImageSkia top_arrow;
46 gfx::ImageSkia* bottom_arrow; 124 gfx::ImageSkia right_arrow;
125 gfx::ImageSkia bottom_arrow;
126
127 int arrow_interior_height; // The height inside the arrow image, in pixels.
47 int border_thickness; 128 int border_thickness;
129 int corner_radius;
48 }; 130 };
49 131
50 // static 132 // static
51 struct BubbleBorder::BorderImages* BubbleBorder::normal_images_ = NULL; 133 struct BubbleBorder::BorderImages*
52 struct BubbleBorder::BorderImages* BubbleBorder::shadow_images_ = NULL; 134 BubbleBorder::border_images_[SHADOW_COUNT] = { NULL };
53
54 // The height inside the arrow image, in pixels.
55 static const int kArrowInteriorHeight = 7;
56 135
57 BubbleBorder::BubbleBorder(ArrowLocation arrow_location, Shadow shadow) 136 BubbleBorder::BubbleBorder(ArrowLocation arrow_location, Shadow shadow)
58 : override_arrow_offset_(0), 137 : override_arrow_offset_(0),
59 arrow_location_(arrow_location), 138 arrow_location_(arrow_location),
60 alignment_(ALIGN_ARROW_TO_MID_ANCHOR), 139 alignment_(ALIGN_ARROW_TO_MID_ANCHOR),
61 background_color_(SK_ColorWHITE) { 140 background_color_(SK_ColorWHITE) {
141 DCHECK(shadow < SHADOW_COUNT);
62 images_ = GetBorderImages(shadow); 142 images_ = GetBorderImages(shadow);
63 143
64 // Calculate horizontal and vertical insets for arrow by ensuring that 144 // Calculate horizontal and vertical insets for arrow by ensuring that
65 // the widest arrow and corner images will have enough room to avoid overlap 145 // the widest arrow and corner images will have enough room to avoid overlap
66 int offset_x = 146 int offset_x =
67 (std::max(images_->top_arrow->width(), 147 (std::max(images_->top_arrow.width(),
68 images_->bottom_arrow->width()) / 2) + 148 images_->bottom_arrow.width()) / 2) +
69 std::max(std::max(images_->top_left->width(), 149 std::max(std::max(images_->top_left.width(),
70 images_->top_right->width()), 150 images_->top_right.width()),
71 std::max(images_->bottom_left->width(), 151 std::max(images_->bottom_left.width(),
72 images_->bottom_right->width())); 152 images_->bottom_right.width()));
73 int offset_y = 153 int offset_y =
74 (std::max(images_->left_arrow->height(), 154 (std::max(images_->left_arrow.height(),
75 images_->right_arrow->height()) / 2) + 155 images_->right_arrow.height()) / 2) +
76 std::max(std::max(images_->top_left->height(), 156 std::max(std::max(images_->top_left.height(),
77 images_->top_right->height()), 157 images_->top_right.height()),
78 std::max(images_->bottom_left->height(), 158 std::max(images_->bottom_left.height(),
79 images_->bottom_right->height())); 159 images_->bottom_right.height()));
80 arrow_offset_ = std::max(offset_x, offset_y); 160 arrow_offset_ = std::max(offset_x, offset_y);
81 } 161 }
82 162
83 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to, 163 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to,
84 const gfx::Size& contents_size) const { 164 const gfx::Size& contents_size) const {
85 // Desired size is size of contents enlarged by the size of the border images. 165 // Desired size is size of contents enlarged by the size of the border images.
86 gfx::Size border_size(contents_size); 166 gfx::Size border_size(contents_size);
87 gfx::Insets insets; 167 gfx::Insets insets;
88 GetInsets(&insets); 168 GetInsets(&insets);
89 border_size.Enlarge(insets.width(), insets.height()); 169 border_size.Enlarge(insets.width(), insets.height());
90 170
91 // Ensure the bubble has a minimum size that draws arrows correctly. 171 // Ensure the bubble has a minimum size that draws arrows correctly.
92 if (is_arrow_on_horizontal(arrow_location_)) 172 if (is_arrow_on_horizontal(arrow_location_))
93 border_size.set_width(std::max(border_size.width(), 2 * arrow_offset_)); 173 border_size.set_width(std::max(border_size.width(), 2 * arrow_offset_));
94 else if (has_arrow(arrow_location_)) 174 else if (has_arrow(arrow_location_))
95 border_size.set_height(std::max(border_size.height(), 2 * arrow_offset_)); 175 border_size.set_height(std::max(border_size.height(), 2 * arrow_offset_));
96 176
97 // Screen position depends on the arrow location. 177 // Screen position depends on the arrow location.
98 // The arrow should overlap the target by some amount since there is space 178 // The bubble should overlap the target by some amount since there is space
99 // for shadow between arrow tip and image bounds. 179 // for shadow between arrow tip/bubble border and image bounds.
100 const int kArrowOverlap = 3;
101 int x = position_relative_to.x(); 180 int x = position_relative_to.x();
102 int y = position_relative_to.y(); 181 int y = position_relative_to.y();
103 int w = position_relative_to.width(); 182 int w = position_relative_to.width();
104 int h = position_relative_to.height(); 183 int h = position_relative_to.height();
105 int arrow_offset = override_arrow_offset_ ? override_arrow_offset_ : 184
106 arrow_offset_; 185 const int arrow_size = images_->arrow_interior_height + kBorderStrokeSize;
186 const int arrow_offset = GetArrowOffset(border_size);
107 187
108 // Calculate bubble x coordinate. 188 // Calculate bubble x coordinate.
109 switch (arrow_location_) { 189 switch (arrow_location_) {
110 case TOP_LEFT: 190 case TOP_LEFT:
111 case BOTTOM_LEFT: 191 case BOTTOM_LEFT:
112 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? w / 2 - arrow_offset : 192 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? w / 2 - arrow_offset :
113 -kArrowOverlap; 193 -(images_->left.width() - kBorderStrokeSize);
114 break; 194 break;
115 195
116 case TOP_RIGHT: 196 case TOP_RIGHT:
117 case BOTTOM_RIGHT: 197 case BOTTOM_RIGHT:
118 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? 198 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ?
119 w / 2 + arrow_offset - border_size.width() + 1 : 199 w / 2 + arrow_offset - border_size.width() + 1 :
120 w - border_size.width() + kArrowOverlap; 200 w - border_size.width() + images_->right.width() - kBorderStrokeSize;
121 break; 201 break;
122 202
123 case LEFT_TOP: 203 case LEFT_TOP:
204 case LEFT_CENTER:
124 case LEFT_BOTTOM: 205 case LEFT_BOTTOM:
125 x += w - kArrowOverlap; 206 x += w - (images_->left_arrow.width() - arrow_size);
126 break; 207 break;
127 208
128 case RIGHT_TOP: 209 case RIGHT_TOP:
210 case RIGHT_CENTER:
129 case RIGHT_BOTTOM: 211 case RIGHT_BOTTOM:
130 x += kArrowOverlap - border_size.width(); 212 x += images_->right_arrow.width() - arrow_size - border_size.width();
213 break;
214
215 case TOP_CENTER:
216 case BOTTOM_CENTER:
217 x += w / 2 - arrow_offset;
131 break; 218 break;
132 219
133 case NONE: 220 case NONE:
134 case FLOAT: 221 case FLOAT:
135 x += w / 2 - border_size.width() / 2; 222 x += w / 2 - border_size.width() / 2;
136 break; 223 break;
137 } 224 }
138 225
139 // Calculate bubble y coordinate. 226 // Calculate bubble y coordinate.
140 switch (arrow_location_) { 227 switch (arrow_location_) {
141 case TOP_LEFT: 228 case TOP_LEFT:
229 case TOP_CENTER:
142 case TOP_RIGHT: 230 case TOP_RIGHT:
143 y += h - kArrowOverlap; 231 y += h - (images_->top_arrow.height() - arrow_size);
144 break; 232 break;
145 233
146 case BOTTOM_LEFT: 234 case BOTTOM_LEFT:
235 case BOTTOM_CENTER:
147 case BOTTOM_RIGHT: 236 case BOTTOM_RIGHT:
148 y += kArrowOverlap - border_size.height(); 237 y += images_->bottom_arrow.height() - arrow_size -
238 border_size.height();
149 break; 239 break;
150 240
151 case LEFT_TOP: 241 case LEFT_TOP:
152 case RIGHT_TOP: 242 case RIGHT_TOP:
153 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? h / 2 - arrow_offset : 243 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? h / 2 - arrow_offset :
154 -kArrowOverlap; 244 -(images_->top.height() - kBorderStrokeSize);
155 break; 245 break;
156 246
157 case LEFT_BOTTOM: 247 case LEFT_BOTTOM:
158 case RIGHT_BOTTOM: 248 case RIGHT_BOTTOM:
159 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? 249 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ?
160 h / 2 + arrow_offset - border_size.height() + 1 : 250 h / 2 + arrow_offset - border_size.height() + 1 :
161 h - border_size.height() + kArrowOverlap; 251 h - border_size.height() + images_->bottom.height() -
252 kBorderStrokeSize;
253 break;
254
255 case LEFT_CENTER:
256 case RIGHT_CENTER:
257 y += h / 2 - arrow_offset;
162 break; 258 break;
163 259
164 case NONE: 260 case NONE:
165 y += h; 261 y += h;
166 break; 262 break;
167 263
168 case FLOAT: 264 case FLOAT:
169 y += h / 2 - border_size.height() / 2; 265 y += h / 2 - border_size.height() / 2;
170 break; 266 break;
171 } 267 }
172 268
173 return gfx::Rect(x, y, border_size.width(), border_size.height()); 269 return gfx::Rect(x, y, border_size.width(), border_size.height());
174 } 270 }
175 271
176 void BubbleBorder::GetInsets(gfx::Insets* insets) const { 272 void BubbleBorder::GetInsets(gfx::Insets* insets) const {
177 return GetInsetsForArrowLocation(insets, arrow_location()); 273 return GetInsetsForArrowLocation(insets, arrow_location());
178 } 274 }
179 275
180 void BubbleBorder::GetInsetsForArrowLocation(gfx::Insets* insets, 276 void BubbleBorder::GetInsetsForArrowLocation(gfx::Insets* insets,
181 ArrowLocation arrow_loc) const { 277 ArrowLocation arrow_loc) const {
182 int top = images_->top->height(); 278 int top = images_->top.height();
183 int bottom = images_->bottom->height(); 279 int bottom = images_->bottom.height();
184 int left = images_->left->width(); 280 int left = images_->left.width();
185 int right = images_->right->width(); 281 int right = images_->right.width();
186 switch (arrow_loc) { 282 switch (arrow_loc) {
187 case TOP_LEFT: 283 case TOP_LEFT:
284 case TOP_CENTER:
188 case TOP_RIGHT: 285 case TOP_RIGHT:
189 top = std::max(top, images_->top_arrow->height()); 286 top = std::max(top, images_->top_arrow.height());
190 break; 287 break;
191 288
192 case BOTTOM_LEFT: 289 case BOTTOM_LEFT:
290 case BOTTOM_CENTER:
193 case BOTTOM_RIGHT: 291 case BOTTOM_RIGHT:
194 bottom = std::max(bottom, images_->bottom_arrow->height()); 292 bottom = std::max(bottom, images_->bottom_arrow.height());
195 break; 293 break;
196 294
197 case LEFT_TOP: 295 case LEFT_TOP:
296 case LEFT_CENTER:
198 case LEFT_BOTTOM: 297 case LEFT_BOTTOM:
199 left = std::max(left, images_->left_arrow->width()); 298 left = std::max(left, images_->left_arrow.width());
200 break; 299 break;
201 300
202 case RIGHT_TOP: 301 case RIGHT_TOP:
302 case RIGHT_CENTER:
203 case RIGHT_BOTTOM: 303 case RIGHT_BOTTOM:
204 right = std::max(right, images_->right_arrow->width()); 304 right = std::max(right, images_->right_arrow.width());
205 break; 305 break;
206 306
207 case NONE: 307 case NONE:
208 case FLOAT: 308 case FLOAT:
209 // Nothing to do. 309 // Nothing to do.
210 break; 310 break;
211 } 311 }
212 insets->Set(top, left, bottom, right); 312 insets->Set(top, left, bottom, right);
213 } 313 }
214 314
215 int BubbleBorder::GetBorderThickness() const { 315 int BubbleBorder::GetBorderThickness() const {
216 return images_->border_thickness; 316 return images_->border_thickness;
217 } 317 }
218 318
219 int BubbleBorder::SetArrowOffset(int offset, const gfx::Size& contents_size) { 319 int BubbleBorder::GetBorderCornerRadius() const {
220 gfx::Size border_size(contents_size); 320 return images_->corner_radius;
221 gfx::Insets insets; 321 }
222 GetInsets(&insets); 322
223 border_size.Enlarge(insets.left() + insets.right(), 323 int BubbleBorder::GetArrowOffset(const gfx::Size& border_size) const {
224 insets.top() + insets.bottom()); 324 int arrow_offset = arrow_offset_;
225 offset = std::max(arrow_offset_, 325 if (override_arrow_offset_) {
226 std::min(offset, (is_arrow_on_horizontal(arrow_location_) ? 326 arrow_offset = override_arrow_offset_;
327 } else if (is_arrow_at_center(arrow_location_)) {
328 if (is_arrow_on_horizontal(arrow_location_))
329 arrow_offset = border_size.width() / 2;
330 else
331 arrow_offset = border_size.height() / 2;
332 }
333
334 // |arrow_offset_| contains the minimum offset required to draw border images
335 // correctly. It's defined in terms of number of pixels from the beginning of
336 // the edge. The maximum arrow offset is the edge size - |arrow_offset_|. The
337 // following statement clamps the calculated arrow offset within that range.
338 return std::max(arrow_offset_,
339 std::min(arrow_offset, (is_arrow_on_horizontal(arrow_location_) ?
227 border_size.width() : border_size.height()) - arrow_offset_)); 340 border_size.width() : border_size.height()) - arrow_offset_));
228 override_arrow_offset_ = offset;
229 return override_arrow_offset_;
230 } 341 }
231 342
232 // static 343 // static
233 BubbleBorder::BorderImages* BubbleBorder::GetBorderImages(Shadow shadow) { 344 BubbleBorder::BorderImages* BubbleBorder::GetBorderImages(Shadow shadow) {
234 if (shadow == SHADOW && shadow_images_ == NULL) { 345 CHECK_LT(shadow, SHADOW_COUNT);
235 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 346
236 shadow_images_ = new BorderImages(); 347 struct BorderImages*& images = border_images_[shadow];
237 shadow_images_->left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_L); 348 if (images)
238 shadow_images_->top_left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_TL); 349 return images;
239 shadow_images_->top = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_T); 350
240 shadow_images_->top_right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_TR); 351 switch (shadow) {
241 shadow_images_->right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_R); 352 case SHADOW:
242 shadow_images_->bottom_right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_BR); 353 images = new BorderImages(kShadowImages,
243 shadow_images_->bottom = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_B); 354 arraysize(kShadowImages),
244 shadow_images_->bottom_left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_BL); 355 0, 10, 4);
245 shadow_images_->left_arrow = new gfx::ImageSkia(); 356 break;
246 shadow_images_->top_arrow = new gfx::ImageSkia(); 357 case NO_SHADOW:
247 shadow_images_->right_arrow = new gfx::ImageSkia(); 358 images = new BorderImages(kNoShadowImages,
248 shadow_images_->bottom_arrow = new gfx::ImageSkia(); 359 arraysize(kNoShadowImages),
249 shadow_images_->border_thickness = 10; 360 7, 0, 4);
250 } else if (shadow == NO_SHADOW && normal_images_ == NULL) { 361 break;
251 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 362 case BIG_SHADOW:
252 normal_images_ = new BorderImages(); 363 images = new BorderImages(kBigShadowImages,
253 normal_images_->left = rb.GetImageSkiaNamed(IDR_BUBBLE_L); 364 arraysize(kBigShadowImages),
254 normal_images_->top_left = rb.GetImageSkiaNamed(IDR_BUBBLE_TL); 365 9, 0, 3);
255 normal_images_->top = rb.GetImageSkiaNamed(IDR_BUBBLE_T); 366 break;
256 normal_images_->top_right = rb.GetImageSkiaNamed(IDR_BUBBLE_TR); 367 case SMALL_SHADOW:
257 normal_images_->right = rb.GetImageSkiaNamed(IDR_BUBBLE_R); 368 images = new BorderImages(kSmallShadowImages,
258 normal_images_->bottom_right = rb.GetImageSkiaNamed(IDR_BUBBLE_BR); 369 arraysize(kSmallShadowImages),
259 normal_images_->bottom = rb.GetImageSkiaNamed(IDR_BUBBLE_B); 370 9, 0, 3);
260 normal_images_->bottom_left = rb.GetImageSkiaNamed(IDR_BUBBLE_BL); 371 break;
261 normal_images_->left_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_L_ARROW); 372 case SHADOW_COUNT:
262 normal_images_->top_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_T_ARROW); 373 NOTREACHED();
263 normal_images_->right_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_R_ARROW); 374 break;
264 normal_images_->bottom_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_B_ARROW);
265 normal_images_->border_thickness = 0;
266 } 375 }
267 return shadow == SHADOW ? shadow_images_ : normal_images_; 376
377 return images;
268 } 378 }
269 379
270 BubbleBorder::~BubbleBorder() {} 380 BubbleBorder::~BubbleBorder() {}
271 381
272 void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { 382 void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
273 // Convenience shorthand variables. 383 // Convenience shorthand variables.
274 const int tl_width = images_->top_left->width(); 384 const int tl_width = images_->top_left.width();
275 const int tl_height = images_->top_left->height(); 385 const int tl_height = images_->top_left.height();
276 const int t_height = images_->top->height(); 386 const int t_height = images_->top.height();
277 const int tr_width = images_->top_right->width(); 387 const int tr_width = images_->top_right.width();
278 const int tr_height = images_->top_right->height(); 388 const int tr_height = images_->top_right.height();
279 const int l_width = images_->left->width(); 389 const int l_width = images_->left.width();
280 const int r_width = images_->right->width(); 390 const int r_width = images_->right.width();
281 const int br_width = images_->bottom_right->width(); 391 const int br_width = images_->bottom_right.width();
282 const int br_height = images_->bottom_right->height(); 392 const int br_height = images_->bottom_right.height();
283 const int b_height = images_->bottom->height(); 393 const int b_height = images_->bottom.height();
284 const int bl_width = images_->bottom_left->width(); 394 const int bl_width = images_->bottom_left.width();
285 const int bl_height = images_->bottom_left->height(); 395 const int bl_height = images_->bottom_left.height();
286 396
287 gfx::Insets insets; 397 gfx::Insets insets;
288 GetInsets(&insets); 398 GetInsets(&insets);
289 const int top = insets.top() - t_height; 399 const int top = insets.top() - t_height;
290 const int bottom = view.height() - insets.bottom() + b_height; 400 const int bottom = view.height() - insets.bottom() + b_height;
291 const int left = insets.left() - l_width; 401 const int left = insets.left() - l_width;
292 const int right = view.width() - insets.right() + r_width; 402 const int right = view.width() - insets.right() + r_width;
293 const int height = bottom - top; 403 const int height = bottom - top;
294 const int width = right - left; 404 const int width = right - left;
295 405
296 // |arrow_offset| is offset of arrow from the begining of the edge. 406 // |arrow_offset| is offset of arrow from the beginning of the edge.
297 int arrow_offset = arrow_offset_; 407 int arrow_offset = GetArrowOffset(view.size());
298 if (override_arrow_offset_) 408 if (!is_arrow_at_center(arrow_location_)) {
299 arrow_offset = override_arrow_offset_; 409 if (is_arrow_on_horizontal(arrow_location_) &&
300 else if (is_arrow_on_horizontal(arrow_location_) && 410 !is_arrow_on_left(arrow_location_)) {
301 !is_arrow_on_left(arrow_location_)) { 411 arrow_offset = view.width() - arrow_offset - 1;
302 arrow_offset = view.width() - arrow_offset - 1; 412 } else if (!is_arrow_on_horizontal(arrow_location_) &&
303 } else if (!is_arrow_on_horizontal(arrow_location_) && 413 !is_arrow_on_top(arrow_location_)) {
304 !is_arrow_on_top(arrow_location_)) { 414 arrow_offset = view.height() - arrow_offset - 1;
305 arrow_offset = view.height() - arrow_offset - 1; 415 }
306 } 416 }
307 417
308 // Left edge. 418 // Left edge.
309 if (arrow_location_ == LEFT_TOP || arrow_location_ == LEFT_BOTTOM) { 419 if (arrow_location_ == LEFT_TOP ||
420 arrow_location_ == LEFT_CENTER ||
421 arrow_location_ == LEFT_BOTTOM) {
310 int start_y = top + tl_height; 422 int start_y = top + tl_height;
311 int before_arrow = 423 int before_arrow =
312 arrow_offset - start_y - images_->left_arrow->height() / 2; 424 arrow_offset - start_y - images_->left_arrow.height() / 2;
313 int after_arrow = height - tl_height - bl_height - 425 int after_arrow = height - tl_height - bl_height -
314 images_->left_arrow->height() - before_arrow; 426 images_->left_arrow.height() - before_arrow;
315 // Shift tip coordinates half pixel so that skia draws the tip correctly. 427 // Shift tip coordinates half pixel so that skia draws the tip correctly.
316 DrawArrowInterior(canvas, 428 DrawArrowInterior(canvas,
317 images_->left_arrow->width() - kArrowInteriorHeight - 0.5f, 429 images_->left_arrow.width() - images_->arrow_interior_height - 0.5f,
318 start_y + before_arrow + images_->left_arrow->height() / 2 - 0.5f); 430 start_y + before_arrow + images_->left_arrow.height() / 2 - 0.5f);
319 DrawEdgeWithArrow(canvas, 431 DrawEdgeWithArrow(canvas,
320 false, 432 false,
321 images_->left, 433 images_->left,
322 images_->left_arrow, 434 images_->left_arrow,
323 left, 435 left,
324 start_y, 436 start_y,
325 before_arrow, 437 before_arrow,
326 after_arrow, 438 after_arrow,
327 images_->left->width() - images_->left_arrow->width()); 439 images_->left.width() - images_->left_arrow.width());
328 } else { 440 } else {
329 canvas->TileImageInt(*images_->left, left, top + tl_height, l_width, 441 canvas->TileImageInt(images_->left, left, top + tl_height, l_width,
330 height - tl_height - bl_height); 442 height - tl_height - bl_height);
331 } 443 }
332 444
333 // Top left corner. 445 // Top left corner.
334 canvas->DrawImageInt(*images_->top_left, left, top); 446 canvas->DrawImageInt(images_->top_left, left, top);
335 447
336 // Top edge. 448 // Top edge.
337 if (arrow_location_ == TOP_LEFT || arrow_location_ == TOP_RIGHT) { 449 if (arrow_location_ == TOP_LEFT ||
450 arrow_location_ == TOP_CENTER ||
451 arrow_location_ == TOP_RIGHT) {
338 int start_x = left + tl_width; 452 int start_x = left + tl_width;
339 int before_arrow = arrow_offset - start_x - images_->top_arrow->width() / 2; 453 int before_arrow = arrow_offset - start_x - images_->top_arrow.width() / 2;
340 int after_arrow = width - tl_width - tr_width - 454 int after_arrow = width - tl_width - tr_width -
341 images_->top_arrow->width() - before_arrow; 455 images_->top_arrow.width() - before_arrow;
342 DrawArrowInterior(canvas, 456 DrawArrowInterior(canvas,
343 start_x + before_arrow + images_->top_arrow->width() / 2, 457 start_x + before_arrow + images_->top_arrow.width() / 2,
344 images_->top_arrow->height() - kArrowInteriorHeight); 458 images_->top_arrow.height() - images_->arrow_interior_height);
345 DrawEdgeWithArrow(canvas, 459 DrawEdgeWithArrow(canvas,
346 true, 460 true,
347 images_->top, 461 images_->top,
348 images_->top_arrow, 462 images_->top_arrow,
349 start_x, 463 start_x,
350 top, 464 top,
351 before_arrow, 465 before_arrow,
352 after_arrow, 466 after_arrow,
353 images_->top->height() - images_->top_arrow->height()); 467 images_->top.height() - images_->top_arrow.height());
354 } else { 468 } else {
355 canvas->TileImageInt(*images_->top, left + tl_width, top, 469 canvas->TileImageInt(images_->top, left + tl_width, top,
356 width - tl_width - tr_width, t_height); 470 width - tl_width - tr_width, t_height);
357 } 471 }
358 472
359 // Top right corner. 473 // Top right corner.
360 canvas->DrawImageInt(*images_->top_right, right - tr_width, top); 474 canvas->DrawImageInt(images_->top_right, right - tr_width, top);
361 475
362 // Right edge. 476 // Right edge.
363 if (arrow_location_ == RIGHT_TOP || arrow_location_ == RIGHT_BOTTOM) { 477 if (arrow_location_ == RIGHT_TOP ||
478 arrow_location_ == RIGHT_CENTER ||
479 arrow_location_ == RIGHT_BOTTOM) {
364 int start_y = top + tr_height; 480 int start_y = top + tr_height;
365 int before_arrow = 481 int before_arrow =
366 arrow_offset - start_y - images_->right_arrow->height() / 2; 482 arrow_offset - start_y - images_->right_arrow.height() / 2;
367 int after_arrow = height - tl_height - bl_height - 483 int after_arrow = height - tl_height - bl_height -
368 images_->right_arrow->height() - before_arrow; 484 images_->right_arrow.height() - before_arrow;
369 // Shift tip coordinates half pixel so that skia draws the tip correctly. 485 // Shift tip coordinates half pixel so that skia draws the tip correctly.
370 DrawArrowInterior(canvas, 486 DrawArrowInterior(canvas,
371 right - r_width + kArrowInteriorHeight - 0.5f, 487 right - r_width + images_->arrow_interior_height - 0.5f,
372 start_y + before_arrow + images_->right_arrow->height() / 2 - 0.5f); 488 start_y + before_arrow + images_->right_arrow.height() / 2 - 0.5f);
373 DrawEdgeWithArrow(canvas, 489 DrawEdgeWithArrow(canvas,
374 false, 490 false,
375 images_->right, 491 images_->right,
376 images_->right_arrow, 492 images_->right_arrow,
377 right - r_width, 493 right - r_width,
378 start_y, 494 start_y,
379 before_arrow, 495 before_arrow,
380 after_arrow, 496 after_arrow,
381 0); 497 0);
382 } else { 498 } else {
383 canvas->TileImageInt(*images_->right, right - r_width, top + tr_height, 499 canvas->TileImageInt(images_->right, right - r_width, top + tr_height,
384 r_width, height - tr_height - br_height); 500 r_width, height - tr_height - br_height);
385 } 501 }
386 502
387 // Bottom right corner. 503 // Bottom right corner.
388 canvas->DrawImageInt(*images_->bottom_right, 504 canvas->DrawImageInt(images_->bottom_right,
389 right - br_width, 505 right - br_width,
390 bottom - br_height); 506 bottom - br_height);
391 507
392 // Bottom edge. 508 // Bottom edge.
393 if (arrow_location_ == BOTTOM_LEFT || arrow_location_ == BOTTOM_RIGHT) { 509 if (arrow_location_ == BOTTOM_LEFT ||
510 arrow_location_ == BOTTOM_CENTER ||
511 arrow_location_ == BOTTOM_RIGHT) {
394 int start_x = left + bl_width; 512 int start_x = left + bl_width;
395 int before_arrow = 513 int before_arrow =
396 arrow_offset - start_x - images_->bottom_arrow->width() / 2; 514 arrow_offset - start_x - images_->bottom_arrow.width() / 2;
397 int after_arrow = width - bl_width - br_width - 515 int after_arrow = width - bl_width - br_width -
398 images_->bottom_arrow->width() - before_arrow; 516 images_->bottom_arrow.width() - before_arrow;
399 DrawArrowInterior(canvas, 517 DrawArrowInterior(canvas,
400 start_x + before_arrow + images_->bottom_arrow->width() / 2, 518 start_x + before_arrow + images_->bottom_arrow.width() / 2,
401 bottom - b_height + kArrowInteriorHeight); 519 bottom - b_height + images_->arrow_interior_height);
402 DrawEdgeWithArrow(canvas, 520 DrawEdgeWithArrow(canvas,
403 true, 521 true,
404 images_->bottom, 522 images_->bottom,
405 images_->bottom_arrow, 523 images_->bottom_arrow,
406 start_x, 524 start_x,
407 bottom - b_height, 525 bottom - b_height,
408 before_arrow, 526 before_arrow,
409 after_arrow, 527 after_arrow,
410 0); 528 0);
411 } else { 529 } else {
412 canvas->TileImageInt(*images_->bottom, left + bl_width, bottom - b_height, 530 canvas->TileImageInt(images_->bottom, left + bl_width, bottom - b_height,
413 width - bl_width - br_width, b_height); 531 width - bl_width - br_width, b_height);
414 } 532 }
415 533
416 // Bottom left corner. 534 // Bottom left corner.
417 canvas->DrawImageInt(*images_->bottom_left, left, bottom - bl_height); 535 canvas->DrawImageInt(images_->bottom_left, left, bottom - bl_height);
418 } 536 }
419 537
420 void BubbleBorder::DrawEdgeWithArrow(gfx::Canvas* canvas, 538 void BubbleBorder::DrawEdgeWithArrow(gfx::Canvas* canvas,
421 bool is_horizontal, 539 bool is_horizontal,
422 gfx::ImageSkia* edge, 540 const gfx::ImageSkia& edge,
423 gfx::ImageSkia* arrow, 541 const gfx::ImageSkia& arrow,
424 int start_x, 542 int start_x,
425 int start_y, 543 int start_y,
426 int before_arrow, 544 int before_arrow,
427 int after_arrow, 545 int after_arrow,
428 int offset) const { 546 int offset) const {
429 /* Here's what the parameters mean: 547 /* Here's what the parameters mean:
430 * start_x 548 * start_x
431 * . 549 * .
432 * . ┌───┐ ┬ offset 550 * . ┌───┐ ┬ offset
433 * start_y..........┌────┬────────┤ ▲ ├────────┬────┐ 551 * start_y..........┌────┬────────┤ ▲ ├────────┬────┐
434 * │ / │--------│∙ ∙│--------│ \ │ 552 * │ / │--------│∙ ∙│--------│ \ │
435 * │ / ├────────┴───┴────────┤ \ │ 553 * │ / ├────────┴───┴────────┤ \ │
436 * ├───┬┘ └┬───┤ 554 * ├───┬┘ └┬───┤
437 * └───┬────┘ └───┬────┘ 555 * └───┬────┘ └───┬────┘
438 * before_arrow ─┘ └─ after_arrow 556 * before_arrow ─┘ └─ after_arrow
439 */ 557 */
440 if (before_arrow) { 558 if (before_arrow) {
441 canvas->TileImageInt(*edge, start_x, start_y, 559 canvas->TileImageInt(edge, start_x, start_y,
442 is_horizontal ? before_arrow : edge->width(), 560 is_horizontal ? before_arrow : edge.width(),
443 is_horizontal ? edge->height() : before_arrow); 561 is_horizontal ? edge.height() : before_arrow);
444 } 562 }
445 563
446 canvas->DrawImageInt(*arrow, 564 canvas->DrawImageInt(arrow,
447 start_x + (is_horizontal ? before_arrow : offset), 565 start_x + (is_horizontal ? before_arrow : offset),
448 start_y + (is_horizontal ? offset : before_arrow)); 566 start_y + (is_horizontal ? offset : before_arrow));
449 567
450 if (after_arrow) { 568 if (after_arrow) {
451 start_x += (is_horizontal ? before_arrow + arrow->width() : 0); 569 start_x += (is_horizontal ? before_arrow + arrow.width() : 0);
452 start_y += (is_horizontal ? 0 : before_arrow + arrow->height()); 570 start_y += (is_horizontal ? 0 : before_arrow + arrow.height());
453 canvas->TileImageInt(*edge, start_x, start_y, 571 canvas->TileImageInt(edge, start_x, start_y,
454 is_horizontal ? after_arrow : edge->width(), 572 is_horizontal ? after_arrow : edge.width(),
455 is_horizontal ? edge->height() : after_arrow); 573 is_horizontal ? edge.height() : after_arrow);
456 } 574 }
457 } 575 }
458 576
459 void BubbleBorder::DrawArrowInterior(gfx::Canvas* canvas, 577 void BubbleBorder::DrawArrowInterior(gfx::Canvas* canvas,
460 float tip_x, 578 float tip_x,
461 float tip_y) const { 579 float tip_y) const {
462 const bool is_horizontal = is_arrow_on_horizontal(arrow_location_); 580 const bool is_horizontal = is_arrow_on_horizontal(arrow_location_);
463 const bool positive_offset = is_horizontal ? 581 const bool positive_offset = is_horizontal ?
464 is_arrow_on_top(arrow_location_) : is_arrow_on_left(arrow_location_); 582 is_arrow_on_top(arrow_location_) : is_arrow_on_left(arrow_location_);
465 const int offset_to_next_vertex = positive_offset ? 583 const int offset_to_next_vertex = positive_offset ?
466 kArrowInteriorHeight : -kArrowInteriorHeight; 584 images_->arrow_interior_height : -images_->arrow_interior_height;
467 585
468 SkPath path; 586 SkPath path;
469 path.incReserve(4); 587 path.incReserve(4);
470 path.moveTo(SkDoubleToScalar(tip_x), SkDoubleToScalar(tip_y)); 588 path.moveTo(SkDoubleToScalar(tip_x), SkDoubleToScalar(tip_y));
471 path.lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex), 589 path.lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex),
472 SkDoubleToScalar(tip_y + offset_to_next_vertex)); 590 SkDoubleToScalar(tip_y + offset_to_next_vertex));
473 if (is_horizontal) { 591 if (is_horizontal) {
474 path.lineTo(SkDoubleToScalar(tip_x - offset_to_next_vertex), 592 path.lineTo(SkDoubleToScalar(tip_x - offset_to_next_vertex),
475 SkDoubleToScalar(tip_y + offset_to_next_vertex)); 593 SkDoubleToScalar(tip_y + offset_to_next_vertex));
476 } else { 594 } else {
(...skipping 22 matching lines...) Expand all
499 // contents, which we need to fill with the background color. 617 // 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 618 // NOTE: This doesn't handle an arrow location of "NONE", which has square top
501 // corners. 619 // corners.
502 SkPaint paint; 620 SkPaint paint;
503 paint.setAntiAlias(true); 621 paint.setAntiAlias(true);
504 paint.setStyle(SkPaint::kFill_Style); 622 paint.setStyle(SkPaint::kFill_Style);
505 paint.setColor(border_->background_color()); 623 paint.setColor(border_->background_color());
506 SkPath path; 624 SkPath path;
507 gfx::Rect bounds(view->GetContentsBounds()); 625 gfx::Rect bounds(view->GetContentsBounds());
508 bounds.Inset(-border_->GetBorderThickness(), -border_->GetBorderThickness()); 626 bounds.Inset(-border_->GetBorderThickness(), -border_->GetBorderThickness());
509 SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); 627 SkScalar radius = SkIntToScalar(border_->GetBorderCornerRadius());
510 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius); 628 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius);
511 canvas->DrawPath(path, paint); 629 canvas->DrawPath(path, paint);
512 } 630 }
513 631
514 } // namespace views 632 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/bubble/bubble_border.h ('k') | ui/views/bubble/bubble_border_2.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698