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" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 shadow_(shadow), | 156 shadow_(shadow), |
157 background_color_(color) { | 157 background_color_(color) { |
158 DCHECK(shadow < SHADOW_COUNT); | 158 DCHECK(shadow < SHADOW_COUNT); |
159 images_ = GetBorderImages(shadow); | 159 images_ = GetBorderImages(shadow); |
160 } | 160 } |
161 | 161 |
162 BubbleBorder::~BubbleBorder() {} | 162 BubbleBorder::~BubbleBorder() {} |
163 | 163 |
164 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect, | 164 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect, |
165 const gfx::Size& contents_size) const { | 165 const gfx::Size& contents_size) const { |
166 // Enlarge the contents size by the thickness of the border images. | |
167 gfx::Size size(contents_size); | |
168 const gfx::Insets insets = GetInsets(); | |
169 size.Enlarge(insets.width(), insets.height()); | |
170 | |
171 // Ensure the bubble is large enough to not overlap border and arrow images. | |
172 const int min = 2 * images_->border_thickness; | |
173 const int min_with_arrow_width = min + images_->top_arrow.width(); | |
174 const int min_with_arrow_thickness = images_->border_thickness + | |
175 std::max(images_->arrow_thickness + images_->border_interior_thickness, | |
176 images_->border_thickness); | |
177 // Only take arrow image sizes into account when the bubble tip is shown. | |
178 if (arrow_paint_type_ == PAINT_TRANSPARENT || !has_arrow(arrow_)) | |
179 size.SetToMax(gfx::Size(min, min)); | |
180 else if (is_arrow_on_horizontal(arrow_)) | |
181 size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness)); | |
182 else | |
183 size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width)); | |
184 | |
185 int x = anchor_rect.x(); | 166 int x = anchor_rect.x(); |
186 int y = anchor_rect.y(); | 167 int y = anchor_rect.y(); |
187 int w = anchor_rect.width(); | 168 int w = anchor_rect.width(); |
188 int h = anchor_rect.height(); | 169 int h = anchor_rect.height(); |
| 170 const gfx::Size size(GetSizeForContentsSize(contents_size)); |
189 const int arrow_offset = GetArrowOffset(size); | 171 const int arrow_offset = GetArrowOffset(size); |
190 const int arrow_size = | 172 const int arrow_size = |
191 images_->arrow_interior_thickness + kStroke - images_->arrow_thickness; | 173 images_->arrow_interior_thickness + kStroke - images_->arrow_thickness; |
192 const bool mid_anchor = alignment_ == ALIGN_ARROW_TO_MID_ANCHOR; | 174 const bool mid_anchor = alignment_ == ALIGN_ARROW_TO_MID_ANCHOR; |
193 | 175 |
194 // Calculate the bubble coordinates based on the border and arrow settings. | 176 // Calculate the bubble coordinates based on the border and arrow settings. |
195 if (is_arrow_on_horizontal(arrow_)) { | 177 if (is_arrow_on_horizontal(arrow_)) { |
196 if (is_arrow_on_left(arrow_)) { | 178 if (is_arrow_on_left(arrow_)) { |
197 x += mid_anchor ? w / 2 - arrow_offset : kStroke - GetBorderThickness(); | 179 x += mid_anchor ? w / 2 - arrow_offset : kStroke - GetBorderThickness(); |
198 } else if (is_arrow_at_center(arrow_)) { | 180 } else if (is_arrow_at_center(arrow_)) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 int first_inset = inset; | 250 int first_inset = inset; |
269 int second_inset = std::max(inset, images_->arrow_thickness); | 251 int second_inset = std::max(inset, images_->arrow_thickness); |
270 if (is_arrow_on_horizontal(arrow_) ? | 252 if (is_arrow_on_horizontal(arrow_) ? |
271 is_arrow_on_top(arrow_) : is_arrow_on_left(arrow_)) | 253 is_arrow_on_top(arrow_) : is_arrow_on_left(arrow_)) |
272 std::swap(first_inset, second_inset); | 254 std::swap(first_inset, second_inset); |
273 return is_arrow_on_horizontal(arrow_) ? | 255 return is_arrow_on_horizontal(arrow_) ? |
274 gfx::Insets(first_inset, inset, second_inset, inset) : | 256 gfx::Insets(first_inset, inset, second_inset, inset) : |
275 gfx::Insets(inset, first_inset, inset, second_inset); | 257 gfx::Insets(inset, first_inset, inset, second_inset); |
276 } | 258 } |
277 | 259 |
| 260 gfx::Size BubbleBorder::GetMinimumSize() const { |
| 261 return GetSizeForContentsSize(gfx::Size()); |
| 262 } |
| 263 |
| 264 gfx::Size BubbleBorder::GetSizeForContentsSize( |
| 265 const gfx::Size& contents_size) const { |
| 266 // Enlarge the contents size by the thickness of the border images. |
| 267 gfx::Size size(contents_size); |
| 268 const gfx::Insets insets = GetInsets(); |
| 269 size.Enlarge(insets.width(), insets.height()); |
| 270 |
| 271 // Ensure the bubble is large enough to not overlap border and arrow images. |
| 272 const int min = 2 * images_->border_thickness; |
| 273 const int min_with_arrow_width = min + images_->top_arrow.width(); |
| 274 const int min_with_arrow_thickness = images_->border_thickness + |
| 275 std::max(images_->arrow_thickness + images_->border_interior_thickness, |
| 276 images_->border_thickness); |
| 277 // Only take arrow image sizes into account when the bubble tip is shown. |
| 278 if (arrow_paint_type_ == PAINT_TRANSPARENT || !has_arrow(arrow_)) |
| 279 size.SetToMax(gfx::Size(min, min)); |
| 280 else if (is_arrow_on_horizontal(arrow_)) |
| 281 size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness)); |
| 282 else |
| 283 size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width)); |
| 284 return size; |
| 285 } |
| 286 |
278 gfx::ImageSkia* BubbleBorder::GetArrowImage() const { | 287 gfx::ImageSkia* BubbleBorder::GetArrowImage() const { |
279 if (!has_arrow(arrow_)) | 288 if (!has_arrow(arrow_)) |
280 return NULL; | 289 return NULL; |
281 if (is_arrow_on_horizontal(arrow_)) { | 290 if (is_arrow_on_horizontal(arrow_)) { |
282 return is_arrow_on_top(arrow_) ? | 291 return is_arrow_on_top(arrow_) ? |
283 &images_->top_arrow : &images_->bottom_arrow; | 292 &images_->top_arrow : &images_->bottom_arrow; |
284 } | 293 } |
285 return is_arrow_on_left(arrow_) ? | 294 return is_arrow_on_left(arrow_) ? |
286 &images_->left_arrow : &images_->right_arrow; | 295 &images_->left_arrow : &images_->right_arrow; |
287 } | 296 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 SkPath path; | 369 SkPath path; |
361 gfx::Rect bounds(view->GetLocalBounds()); | 370 gfx::Rect bounds(view->GetLocalBounds()); |
362 bounds.Inset(border_->GetInsets()); | 371 bounds.Inset(border_->GetInsets()); |
363 | 372 |
364 SkScalar radius = SkIntToScalar(border_->GetBorderCornerRadius()); | 373 SkScalar radius = SkIntToScalar(border_->GetBorderCornerRadius()); |
365 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius); | 374 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius); |
366 canvas->DrawPath(path, paint); | 375 canvas->DrawPath(path, paint); |
367 } | 376 } |
368 | 377 |
369 } // namespace views | 378 } // namespace views |
OLD | NEW |