Chromium Code Reviews| 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 "third_party/skia/include/core/SkPaint.h" | 10 #include "third_party/skia/include/core/SkPaint.h" |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 157 BubbleBorder::~BubbleBorder() {} | 157 BubbleBorder::~BubbleBorder() {} |
| 158 | 158 |
| 159 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect, | 159 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect, |
| 160 const gfx::Size& contents_size) const { | 160 const gfx::Size& contents_size) const { |
| 161 int x = anchor_rect.x(); | 161 int x = anchor_rect.x(); |
| 162 int y = anchor_rect.y(); | 162 int y = anchor_rect.y(); |
| 163 int w = anchor_rect.width(); | 163 int w = anchor_rect.width(); |
| 164 int h = anchor_rect.height(); | 164 int h = anchor_rect.height(); |
| 165 const gfx::Size size(GetSizeForContentsSize(contents_size)); | 165 const gfx::Size size(GetSizeForContentsSize(contents_size)); |
| 166 const int arrow_offset = GetArrowOffset(size); | 166 const int arrow_offset = GetArrowOffset(size); |
| 167 const int arrow_size = | 167 // |arrow_shift| is necessary to visually align the tip of the bubble arrow |
| 168 // with the anchor point. This shift is an inverse of the shadow thickness | |
| 169 // and the shadow thickness can be calculated as total arrow image height | |
|
Evan Stade
2016/03/18 04:53:32
nit: I'd leave off everything after the second lin
varkha
2016/03/18 05:23:08
Done.
| |
| 170 // (|arrow_thickness|) minus the arrow tip height (|arrow_interior_thickness|) | |
| 171 // and minus the flat stroke thickness (|kStroke|). | |
| 172 int arrow_shift = | |
| 168 images_->arrow_interior_thickness + kStroke - images_->arrow_thickness; | 173 images_->arrow_interior_thickness + kStroke - images_->arrow_thickness; |
| 174 // When arrow is painted transparently the visible border of the bubble needs | |
| 175 // to be positioned at the same bounds as when the arrow is shown. Shift | |
|
Evan Stade
2016/03/18 04:53:32
nit: I'd leave off everything past the first sente
varkha
2016/03/18 05:23:08
Done.
| |
| 176 // bounds additionally by the visible arrow tip thickness. | |
| 177 if (arrow_paint_type_ == PAINT_TRANSPARENT) | |
| 178 arrow_shift += images_->arrow_interior_thickness; | |
|
Evan Stade
2016/03/18 04:53:32
just to double check --- you don't need a + kStrok
varkha
2016/03/18 05:23:08
Not if I want the top or bottom horizontal lines o
| |
| 169 const bool mid_anchor = alignment_ == ALIGN_ARROW_TO_MID_ANCHOR; | 179 const bool mid_anchor = alignment_ == ALIGN_ARROW_TO_MID_ANCHOR; |
| 170 | 180 |
| 171 // Calculate the bubble coordinates based on the border and arrow settings. | 181 // Calculate the bubble coordinates based on the border and arrow settings. |
| 172 if (is_arrow_on_horizontal(arrow_)) { | 182 if (is_arrow_on_horizontal(arrow_)) { |
| 173 if (is_arrow_on_left(arrow_)) { | 183 if (is_arrow_on_left(arrow_)) { |
| 174 x += mid_anchor ? w / 2 - arrow_offset : kStroke - GetBorderThickness(); | 184 x += mid_anchor ? w / 2 - arrow_offset : kStroke - GetBorderThickness(); |
| 175 } else if (is_arrow_at_center(arrow_)) { | 185 } else if (is_arrow_at_center(arrow_)) { |
| 176 x += w / 2 - arrow_offset; | 186 x += w / 2 - arrow_offset; |
| 177 } else { | 187 } else { |
| 178 x += mid_anchor ? w / 2 + arrow_offset - size.width() : | 188 x += mid_anchor ? w / 2 + arrow_offset - size.width() : |
| 179 w - size.width() + GetBorderThickness() - kStroke; | 189 w - size.width() + GetBorderThickness() - kStroke; |
| 180 } | 190 } |
| 181 y += is_arrow_on_top(arrow_) ? h + arrow_size : -arrow_size - size.height(); | 191 y += is_arrow_on_top(arrow_) ? h + arrow_shift |
| 192 : -arrow_shift - size.height(); | |
| 182 } else if (has_arrow(arrow_)) { | 193 } else if (has_arrow(arrow_)) { |
| 183 x += is_arrow_on_left(arrow_) ? w + arrow_size : -arrow_size - size.width(); | 194 x += is_arrow_on_left(arrow_) ? w + arrow_shift |
| 195 : -arrow_shift - size.width(); | |
| 184 if (is_arrow_on_top(arrow_)) { | 196 if (is_arrow_on_top(arrow_)) { |
| 185 y += mid_anchor ? h / 2 - arrow_offset : kStroke - GetBorderThickness(); | 197 y += mid_anchor ? h / 2 - arrow_offset : kStroke - GetBorderThickness(); |
| 186 } else if (is_arrow_at_center(arrow_)) { | 198 } else if (is_arrow_at_center(arrow_)) { |
| 187 y += h / 2 - arrow_offset; | 199 y += h / 2 - arrow_offset; |
| 188 } else { | 200 } else { |
| 189 y += mid_anchor ? h / 2 + arrow_offset - size.height() : | 201 y += mid_anchor ? h / 2 + arrow_offset - size.height() : |
| 190 h - size.height() + GetBorderThickness() - kStroke; | 202 h - size.height() + GetBorderThickness() - kStroke; |
| 191 } | 203 } |
| 192 } else { | 204 } else { |
| 193 x += (w - size.width()) / 2; | 205 x += (w - size.width()) / 2; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 canvas->sk_canvas()->clipRect(arrow_rect, SkRegion::kDifference_Op); | 258 canvas->sk_canvas()->clipRect(arrow_rect, SkRegion::kDifference_Op); |
| 247 Painter::PaintPainterAt(canvas, images_->border_painter.get(), bounds); | 259 Painter::PaintPainterAt(canvas, images_->border_painter.get(), bounds); |
| 248 canvas->Restore(); | 260 canvas->Restore(); |
| 249 | 261 |
| 250 DrawArrow(canvas, arrow_bounds); | 262 DrawArrow(canvas, arrow_bounds); |
| 251 } | 263 } |
| 252 | 264 |
| 253 gfx::Insets BubbleBorder::GetInsets() const { | 265 gfx::Insets BubbleBorder::GetInsets() const { |
| 254 // The insets contain the stroke and shadow pixels outside the bubble fill. | 266 // The insets contain the stroke and shadow pixels outside the bubble fill. |
| 255 const int inset = GetBorderThickness(); | 267 const int inset = GetBorderThickness(); |
| 256 if ((arrow_paint_type_ == PAINT_NONE) || !has_arrow(arrow_)) | 268 if (arrow_paint_type_ != PAINT_NORMAL || !has_arrow(arrow_)) |
| 257 return gfx::Insets(inset); | 269 return gfx::Insets(inset); |
| 258 | 270 |
| 259 int first_inset = inset; | 271 int first_inset = inset; |
| 260 int second_inset = std::max(inset, images_->arrow_thickness); | 272 int second_inset = std::max(inset, images_->arrow_thickness); |
| 261 if (is_arrow_on_horizontal(arrow_) ? | 273 if (is_arrow_on_horizontal(arrow_) ? |
| 262 is_arrow_on_top(arrow_) : is_arrow_on_left(arrow_)) | 274 is_arrow_on_top(arrow_) : is_arrow_on_left(arrow_)) |
| 263 std::swap(first_inset, second_inset); | 275 std::swap(first_inset, second_inset); |
| 264 return is_arrow_on_horizontal(arrow_) ? | 276 return is_arrow_on_horizontal(arrow_) ? |
| 265 gfx::Insets(first_inset, inset, second_inset, inset) : | 277 gfx::Insets(first_inset, inset, second_inset, inset) : |
| 266 gfx::Insets(inset, first_inset, inset, second_inset); | 278 gfx::Insets(inset, first_inset, inset, second_inset); |
| 267 } | 279 } |
| 268 | 280 |
| 269 gfx::Size BubbleBorder::GetMinimumSize() const { | 281 gfx::Size BubbleBorder::GetMinimumSize() const { |
| 270 return GetSizeForContentsSize(gfx::Size()); | 282 return GetSizeForContentsSize(gfx::Size()); |
| 271 } | 283 } |
| 272 | 284 |
| 273 gfx::Size BubbleBorder::GetSizeForContentsSize( | 285 gfx::Size BubbleBorder::GetSizeForContentsSize( |
| 274 const gfx::Size& contents_size) const { | 286 const gfx::Size& contents_size) const { |
| 275 // Enlarge the contents size by the thickness of the border images. | 287 // Enlarge the contents size by the thickness of the border images. |
| 276 gfx::Size size(contents_size); | 288 gfx::Size size(contents_size); |
| 277 const gfx::Insets insets = GetInsets(); | 289 const gfx::Insets insets = GetInsets(); |
| 278 size.Enlarge(insets.width(), insets.height()); | 290 size.Enlarge(insets.width(), insets.height()); |
| 279 | 291 |
| 280 // Ensure the bubble is large enough to not overlap border and arrow images. | 292 // Ensure the bubble is large enough to not overlap border and arrow images. |
| 281 const int min = 2 * images_->border_thickness; | 293 const int min = 2 * images_->border_thickness; |
| 294 // Only take arrow image sizes into account when the bubble tip is shown. | |
| 295 if (arrow_paint_type_ != PAINT_NORMAL || !has_arrow(arrow_)) { | |
| 296 size.SetToMax(gfx::Size(min, min)); | |
| 297 return size; | |
| 298 } | |
| 282 const int min_with_arrow_width = min + images_->arrow_width; | 299 const int min_with_arrow_width = min + images_->arrow_width; |
| 283 const int min_with_arrow_thickness = images_->border_thickness + | 300 const int min_with_arrow_thickness = images_->border_thickness + |
| 284 std::max(images_->arrow_thickness + images_->border_interior_thickness, | 301 std::max(images_->arrow_thickness + images_->border_interior_thickness, |
| 285 images_->border_thickness); | 302 images_->border_thickness); |
| 286 // Only take arrow image sizes into account when the bubble tip is shown. | 303 if (is_arrow_on_horizontal(arrow_)) |
| 287 if (arrow_paint_type_ == PAINT_NONE || !has_arrow(arrow_)) | |
| 288 size.SetToMax(gfx::Size(min, min)); | |
| 289 else if (is_arrow_on_horizontal(arrow_)) | |
| 290 size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness)); | 304 size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness)); |
| 291 else | 305 else |
| 292 size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width)); | 306 size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width)); |
| 293 return size; | 307 return size; |
| 294 } | 308 } |
| 295 | 309 |
| 296 gfx::ImageSkia* BubbleBorder::GetArrowImage() const { | 310 gfx::ImageSkia* BubbleBorder::GetArrowImage() const { |
| 297 if (!has_arrow(arrow_)) | 311 if (!has_arrow(arrow_)) |
| 298 return NULL; | 312 return NULL; |
| 299 if (is_arrow_on_horizontal(arrow_)) { | 313 if (is_arrow_on_horizontal(arrow_)) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 394 paint.setStyle(SkPaint::kFill_Style); | 408 paint.setStyle(SkPaint::kFill_Style); |
| 395 paint.setColor(border_->background_color()); | 409 paint.setColor(border_->background_color()); |
| 396 SkPath path; | 410 SkPath path; |
| 397 gfx::Rect bounds(view->GetLocalBounds()); | 411 gfx::Rect bounds(view->GetLocalBounds()); |
| 398 bounds.Inset(border_->GetInsets()); | 412 bounds.Inset(border_->GetInsets()); |
| 399 | 413 |
| 400 canvas->DrawRoundRect(bounds, border_->GetBorderCornerRadius(), paint); | 414 canvas->DrawRoundRect(bounds, border_->GetBorderCornerRadius(), paint); |
| 401 } | 415 } |
| 402 | 416 |
| 403 } // namespace views | 417 } // namespace views |
| OLD | NEW |