| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 EXPECT_EQ(cases[i].expected_without_arrow, | 313 EXPECT_EQ(cases[i].expected_without_arrow, |
| 314 border.GetSizeForContentsSize(cases[i].content)); | 314 border.GetSizeForContentsSize(cases[i].content)); |
| 315 | 315 |
| 316 border.set_paint_arrow(BubbleBorder::PAINT_NONE); | 316 border.set_paint_arrow(BubbleBorder::PAINT_NONE); |
| 317 EXPECT_EQ(cases[i].expected_without_arrow, | 317 EXPECT_EQ(cases[i].expected_without_arrow, |
| 318 border.GetSizeForContentsSize(cases[i].content)); | 318 border.GetSizeForContentsSize(cases[i].content)); |
| 319 } | 319 } |
| 320 } | 320 } |
| 321 | 321 |
| 322 TEST_F(BubbleBorderTest, GetBoundsOriginTest) { | 322 TEST_F(BubbleBorderTest, GetBoundsOriginTest) { |
| 323 views::BubbleBorder border(BubbleBorder::TOP_LEFT, | 323 for (int i = 0; i < BubbleBorder::SHADOW_COUNT; ++i) { |
| 324 BubbleBorder::NO_SHADOW, | 324 const BubbleBorder::Shadow shadow = static_cast<BubbleBorder::Shadow>(i); |
| 325 SK_ColorWHITE); | 325 SCOPED_TRACE(testing::Message() << "BubbleBorder::Shadow: " << shadow); |
| 326 views::BubbleBorder border(BubbleBorder::TOP_LEFT, shadow, SK_ColorWHITE); |
| 327 #if defined(OS_MACOSX) |
| 328 // Mac always uses NO_ASSETS, no matter what we tell it to use. No point in |
| 329 // testing any other shadow. |
| 330 EXPECT_EQ(BubbleBorder::NO_ASSETS, border.shadow()); |
| 331 if (shadow != BubbleBorder::NO_ASSETS) |
| 332 continue; |
| 333 #endif |
| 326 | 334 |
| 327 const gfx::Rect kAnchor(100, 100, 20, 30); | 335 const gfx::Rect kAnchor(100, 100, 20, 30); |
| 328 const gfx::Size kContentSize(50, 60); | 336 const gfx::Size kContentSize(500, 600); |
| 329 | 337 |
| 330 const views::internal::BorderImages* kImages = border.GetImagesForTest(); | 338 const views::internal::BorderImages* kImages = border.GetImagesForTest(); |
| 331 | 339 |
| 332 border.set_arrow(BubbleBorder::TOP_LEFT); | 340 border.set_arrow(BubbleBorder::TOP_LEFT); |
| 333 const gfx::Size kTotalSizeWithHorizArrow = | 341 const gfx::Size kTotalSizeWithHorizArrow = |
| 334 border.GetSizeForContentsSize(kContentSize); | 342 border.GetSizeForContentsSize(kContentSize); |
| 335 | 343 |
| 336 border.set_arrow(BubbleBorder::RIGHT_BOTTOM); | 344 border.set_arrow(BubbleBorder::RIGHT_BOTTOM); |
| 337 const gfx::Size kTotalSizeWithVertArrow = | 345 const gfx::Size kTotalSizeWithVertArrow = |
| 338 border.GetSizeForContentsSize(kContentSize); | 346 border.GetSizeForContentsSize(kContentSize); |
| 339 | 347 |
| 340 border.set_arrow(BubbleBorder::NONE); | 348 border.set_arrow(BubbleBorder::NONE); |
| 341 const gfx::Size kTotalSizeWithNoArrow = | 349 const gfx::Size kTotalSizeWithNoArrow = |
| 342 border.GetSizeForContentsSize(kContentSize); | 350 border.GetSizeForContentsSize(kContentSize); |
| 343 | 351 |
| 344 const int kBorderThickness = border.GetBorderThickness(); | 352 const int kBorderThickness = border.GetBorderThickness(); |
| 345 | 353 |
| 346 const int kArrowOffsetForHorizCenter = kTotalSizeWithHorizArrow.width() / 2; | 354 const int kArrowOffsetForHorizCenter = kTotalSizeWithHorizArrow.width() / 2; |
| 347 const int kArrowOffsetForVertCenter = kTotalSizeWithVertArrow.height() / 2; | 355 const int kArrowOffsetForVertCenter = kTotalSizeWithVertArrow.height() / 2; |
| 348 const int kArrowOffsetForNotCenter = | 356 const int kArrowOffsetForNotCenter = |
| 349 kImages->border_thickness + (kImages->arrow_width / 2); | 357 kImages->border_thickness + (kImages->arrow_width / 2); |
| 350 | 358 |
| 351 const int kArrowThickness = kImages->arrow_interior_thickness; | 359 const int kStrokeWidth = |
| 352 const int kArrowShift = | 360 shadow == BubbleBorder::NO_ASSETS ? 0 : BubbleBorder::kStroke; |
| 353 kArrowThickness + BubbleBorder::kStroke - kImages->arrow_thickness; | |
| 354 const int kHeightDifference = kTotalSizeWithHorizArrow.height() - | |
| 355 kTotalSizeWithNoArrow.height(); | |
| 356 const int kWidthDifference = kTotalSizeWithVertArrow.width() - | |
| 357 kTotalSizeWithNoArrow.width(); | |
| 358 EXPECT_EQ(kHeightDifference, kWidthDifference); | |
| 359 EXPECT_EQ(kHeightDifference, kArrowThickness); | |
| 360 | 361 |
| 361 const int kTopHorizArrowY = kAnchor.y() + kAnchor.height() + kArrowShift; | 362 const int kArrowThickness = kImages->arrow_interior_thickness; |
| 362 const int kBottomHorizArrowY = | 363 const int kArrowShift = |
| 363 kAnchor.y() - kArrowShift - kTotalSizeWithHorizArrow.height(); | 364 kArrowThickness + kStrokeWidth - kImages->arrow_thickness; |
| 364 const int kLeftVertArrowX = kAnchor.x() + kAnchor.width() + kArrowShift; | 365 const int kHeightDifference = |
| 365 const int kRightVertArrowX = | 366 kTotalSizeWithHorizArrow.height() - kTotalSizeWithNoArrow.height(); |
| 366 kAnchor.x() - kArrowShift - kTotalSizeWithVertArrow.width(); | 367 const int kWidthDifference = |
| 368 kTotalSizeWithVertArrow.width() - kTotalSizeWithNoArrow.width(); |
| 369 EXPECT_EQ(kHeightDifference, kWidthDifference); |
| 367 | 370 |
| 368 struct TestCase { | 371 // The arrow only makes a difference in height if it is longer than the |
| 369 BubbleBorder::Arrow arrow; | 372 // shadow. |
| 370 BubbleBorder::BubbleAlignment alignment; | 373 const int kExpectedHeightDifference = |
| 371 int expected_x; | 374 std::max(kImages->arrow_thickness + kImages->border_interior_thickness, |
| 372 int expected_y; | 375 kImages->border_thickness) - |
| 373 }; | 376 std::max(kImages->border_interior_thickness, kImages->border_thickness); |
| 377 EXPECT_EQ(kExpectedHeightDifference, kHeightDifference) |
| 378 << "Size with arrow: " << kTotalSizeWithHorizArrow.ToString() |
| 379 << " vs. size without arrow: " << kTotalSizeWithNoArrow.ToString(); |
| 374 | 380 |
| 375 TestCase cases[] = { | 381 const int kTopHorizArrowY = kAnchor.y() + kAnchor.height() + kArrowShift; |
| 376 // Horizontal arrow tests. | 382 const int kBottomHorizArrowY = |
| 377 { BubbleBorder::TOP_LEFT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | 383 kAnchor.y() - kArrowShift - kTotalSizeWithHorizArrow.height(); |
| 378 kAnchor.CenterPoint().x() - kArrowOffsetForNotCenter, kTopHorizArrowY }, | 384 const int kLeftVertArrowX = kAnchor.x() + kAnchor.width() + kArrowShift; |
| 379 { BubbleBorder::TOP_LEFT, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, | 385 const int kRightVertArrowX = |
| 380 kAnchor.x() + BubbleBorder::kStroke - kBorderThickness, kTopHorizArrowY }, | 386 kAnchor.x() - kArrowShift - kTotalSizeWithVertArrow.width(); |
| 381 { BubbleBorder::TOP_CENTER, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | |
| 382 kAnchor.CenterPoint().x() - kArrowOffsetForHorizCenter, kTopHorizArrowY }, | |
| 383 { BubbleBorder::BOTTOM_RIGHT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | |
| 384 kAnchor.CenterPoint().x() + kArrowOffsetForNotCenter - | |
| 385 kTotalSizeWithHorizArrow.width(), kBottomHorizArrowY }, | |
| 386 { BubbleBorder::BOTTOM_RIGHT, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, | |
| 387 kAnchor.x() + kAnchor.width() - kTotalSizeWithHorizArrow.width() + | |
| 388 kBorderThickness - BubbleBorder::kStroke, kBottomHorizArrowY }, | |
| 389 | 387 |
| 390 // Vertical arrow tests. | 388 struct TestCase { |
| 391 { BubbleBorder::LEFT_TOP, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | 389 BubbleBorder::Arrow arrow; |
| 392 kLeftVertArrowX, kAnchor.CenterPoint().y() - kArrowOffsetForNotCenter }, | 390 BubbleBorder::BubbleAlignment alignment; |
| 393 { BubbleBorder::LEFT_TOP, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, | 391 int expected_x; |
| 394 kLeftVertArrowX, kAnchor.y() + BubbleBorder::kStroke - kBorderThickness }, | 392 int expected_y; |
| 395 { BubbleBorder::LEFT_CENTER, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | 393 }; |
| 396 kLeftVertArrowX, kAnchor.CenterPoint().y() - kArrowOffsetForVertCenter }, | |
| 397 { BubbleBorder::RIGHT_BOTTOM, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | |
| 398 kRightVertArrowX, kAnchor.CenterPoint().y() + kArrowOffsetForNotCenter - | |
| 399 kTotalSizeWithVertArrow.height() }, | |
| 400 { BubbleBorder::RIGHT_BOTTOM, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, | |
| 401 kRightVertArrowX, kAnchor.y() + kAnchor.height() - | |
| 402 kTotalSizeWithVertArrow.height() + kBorderThickness - | |
| 403 BubbleBorder::kStroke }, | |
| 404 | 394 |
| 405 // No arrow tests. | 395 TestCase cases[] = { |
| 406 { BubbleBorder::NONE, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | 396 // Horizontal arrow tests. |
| 407 kAnchor.x() + (kAnchor.width() - kTotalSizeWithNoArrow.width()) / 2, | 397 {BubbleBorder::TOP_LEFT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, |
| 408 kAnchor.y() + kAnchor.height() }, | 398 kAnchor.CenterPoint().x() - kArrowOffsetForNotCenter, kTopHorizArrowY}, |
| 409 { BubbleBorder::FLOAT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | 399 {BubbleBorder::TOP_LEFT, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, |
| 410 kAnchor.x() + (kAnchor.width() - kTotalSizeWithNoArrow.width()) / 2, | 400 kAnchor.x() + kStrokeWidth - kBorderThickness, kTopHorizArrowY}, |
| 411 kAnchor.y() + (kAnchor.height() - kTotalSizeWithNoArrow.height()) / 2 }, | 401 {BubbleBorder::TOP_CENTER, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, |
| 412 }; | 402 kAnchor.CenterPoint().x() - kArrowOffsetForHorizCenter, |
| 403 kTopHorizArrowY}, |
| 404 {BubbleBorder::BOTTOM_RIGHT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, |
| 405 kAnchor.CenterPoint().x() + kArrowOffsetForNotCenter - |
| 406 kTotalSizeWithHorizArrow.width(), |
| 407 kBottomHorizArrowY}, |
| 408 {BubbleBorder::BOTTOM_RIGHT, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, |
| 409 kAnchor.x() + kAnchor.width() - kTotalSizeWithHorizArrow.width() + |
| 410 kBorderThickness - kStrokeWidth, |
| 411 kBottomHorizArrowY}, |
| 413 | 412 |
| 414 for (size_t i = 0; i < arraysize(cases); ++i) { | 413 // Vertical arrow tests. |
| 415 SCOPED_TRACE(base::StringPrintf("i=%d arrow=%d alignment=%d", | 414 {BubbleBorder::LEFT_TOP, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, |
| 416 static_cast<int>(i), cases[i].arrow, cases[i].alignment)); | 415 kLeftVertArrowX, kAnchor.CenterPoint().y() - kArrowOffsetForNotCenter}, |
| 417 const BubbleBorder::Arrow arrow = cases[i].arrow; | 416 {BubbleBorder::LEFT_TOP, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, |
| 418 border.set_arrow(arrow); | 417 kLeftVertArrowX, kAnchor.y() + kStrokeWidth - kBorderThickness}, |
| 419 border.set_alignment(cases[i].alignment); | 418 {BubbleBorder::LEFT_CENTER, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, |
| 419 kLeftVertArrowX, |
| 420 kAnchor.CenterPoint().y() - kArrowOffsetForVertCenter}, |
| 421 {BubbleBorder::RIGHT_BOTTOM, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, |
| 422 kRightVertArrowX, |
| 423 kAnchor.CenterPoint().y() + kArrowOffsetForNotCenter - |
| 424 kTotalSizeWithVertArrow.height()}, |
| 425 {BubbleBorder::RIGHT_BOTTOM, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, |
| 426 kRightVertArrowX, |
| 427 kAnchor.y() + kAnchor.height() - kTotalSizeWithVertArrow.height() + |
| 428 kBorderThickness - kStrokeWidth}, |
| 420 | 429 |
| 421 border.set_paint_arrow(BubbleBorder::PAINT_NORMAL); | 430 // No arrow tests. |
| 422 gfx::Point origin = border.GetBounds(kAnchor, kContentSize).origin(); | 431 {BubbleBorder::NONE, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, |
| 423 int expected_x = cases[i].expected_x; | 432 kAnchor.x() + (kAnchor.width() - kTotalSizeWithNoArrow.width()) / 2, |
| 424 int expected_y = cases[i].expected_y; | 433 kAnchor.y() + kAnchor.height()}, |
| 425 EXPECT_EQ(expected_x, origin.x()); | 434 {BubbleBorder::FLOAT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, |
| 426 EXPECT_EQ(expected_y, origin.y()); | 435 kAnchor.x() + (kAnchor.width() - kTotalSizeWithNoArrow.width()) / 2, |
| 436 kAnchor.y() + (kAnchor.height() - kTotalSizeWithNoArrow.height()) / 2}, |
| 437 }; |
| 427 | 438 |
| 428 border.set_paint_arrow(BubbleBorder::PAINT_TRANSPARENT); | 439 for (size_t i = 0; i < arraysize(cases); ++i) { |
| 429 origin = border.GetBounds(kAnchor, kContentSize).origin(); | 440 SCOPED_TRACE(base::StringPrintf("i=%d arrow=%d alignment=%d", |
| 430 if (border.is_arrow_on_horizontal(arrow)) { | 441 static_cast<int>(i), cases[i].arrow, |
| 431 expected_y += BubbleBorder::is_arrow_on_top(arrow) | 442 cases[i].alignment)); |
| 432 ? kArrowThickness : (-kArrowThickness + kHeightDifference); | 443 const BubbleBorder::Arrow arrow = cases[i].arrow; |
| 433 } else if (BubbleBorder::has_arrow(arrow)) { | 444 border.set_arrow(arrow); |
| 434 expected_x += BubbleBorder::is_arrow_on_left(arrow) | 445 border.set_alignment(cases[i].alignment); |
| 435 ? kArrowThickness : (-kArrowThickness + kWidthDifference); | 446 |
| 447 border.set_paint_arrow(BubbleBorder::PAINT_NORMAL); |
| 448 gfx::Point origin = border.GetBounds(kAnchor, kContentSize).origin(); |
| 449 int expected_x = cases[i].expected_x; |
| 450 int expected_y = cases[i].expected_y; |
| 451 EXPECT_EQ(expected_x, origin.x()); |
| 452 EXPECT_EQ(expected_y, origin.y()); |
| 453 |
| 454 border.set_paint_arrow(BubbleBorder::PAINT_TRANSPARENT); |
| 455 origin = border.GetBounds(kAnchor, kContentSize).origin(); |
| 456 if (border.is_arrow_on_horizontal(arrow)) { |
| 457 expected_y += BubbleBorder::is_arrow_on_top(arrow) |
| 458 ? kArrowThickness |
| 459 : (-kArrowThickness + kHeightDifference); |
| 460 } else if (BubbleBorder::has_arrow(arrow)) { |
| 461 expected_x += BubbleBorder::is_arrow_on_left(arrow) |
| 462 ? kArrowThickness |
| 463 : (-kArrowThickness + kWidthDifference); |
| 464 } |
| 465 EXPECT_EQ(expected_x, origin.x()); |
| 466 EXPECT_EQ(expected_y, origin.y()); |
| 467 |
| 468 border.set_paint_arrow(BubbleBorder::PAINT_NONE); |
| 469 origin = border.GetBounds(kAnchor, kContentSize).origin(); |
| 470 expected_x = cases[i].expected_x; |
| 471 expected_y = cases[i].expected_y; |
| 472 if (border.is_arrow_on_horizontal(arrow) && |
| 473 !BubbleBorder::is_arrow_on_top(arrow)) { |
| 474 expected_y += kHeightDifference; |
| 475 } else if (BubbleBorder::has_arrow(arrow) && |
| 476 !border.is_arrow_on_horizontal(arrow) && |
| 477 !BubbleBorder::is_arrow_on_left(arrow)) { |
| 478 expected_x += kWidthDifference; |
| 479 } |
| 480 EXPECT_EQ(expected_x, origin.x()); |
| 481 EXPECT_EQ(expected_y, origin.y()); |
| 436 } | 482 } |
| 437 EXPECT_EQ(expected_x, origin.x()); | 483 } |
| 438 EXPECT_EQ(expected_y, origin.y()); | |
| 439 | |
| 440 border.set_paint_arrow(BubbleBorder::PAINT_NONE); | |
| 441 origin = border.GetBounds(kAnchor, kContentSize).origin(); | |
| 442 expected_x = cases[i].expected_x; | |
| 443 expected_y = cases[i].expected_y; | |
| 444 if (border.is_arrow_on_horizontal(arrow) && | |
| 445 !BubbleBorder::is_arrow_on_top(arrow)) { | |
| 446 expected_y += kHeightDifference; | |
| 447 } else if (BubbleBorder::has_arrow(arrow) && | |
| 448 !border.is_arrow_on_horizontal(arrow) && | |
| 449 !BubbleBorder::is_arrow_on_left(arrow)) { | |
| 450 expected_x += kWidthDifference; | |
| 451 } | |
| 452 EXPECT_EQ(expected_x, origin.x()); | |
| 453 EXPECT_EQ(expected_y, origin.y()); | |
| 454 } | |
| 455 } | 484 } |
| 456 | 485 |
| 457 // Ensure all the shadow types pass some size validation and paint sanely. | 486 // Ensure all the shadow types pass some size validation and paint sanely. |
| 458 TEST_F(BubbleBorderTest, ShadowTypes) { | 487 TEST_F(BubbleBorderTest, ShadowTypes) { |
| 459 const gfx::Rect rect(0, 0, 320, 200); | 488 const gfx::Rect rect(0, 0, 320, 200); |
| 460 View paint_view; | 489 View paint_view; |
| 461 paint_view.SetBoundsRect(rect); | 490 paint_view.SetBoundsRect(rect); |
| 462 | 491 |
| 463 for (int i = 0; i < BubbleBorder::SHADOW_COUNT; ++i) { | 492 for (int i = 0; i < BubbleBorder::SHADOW_COUNT; ++i) { |
| 464 BubbleBorder::Shadow shadow = static_cast<BubbleBorder::Shadow>(i); | 493 BubbleBorder::Shadow shadow = static_cast<BubbleBorder::Shadow>(i); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 477 EXPECT_GE(border_images->border_thickness, | 506 EXPECT_GE(border_images->border_thickness, |
| 478 border_images->border_interior_thickness); | 507 border_images->border_interior_thickness); |
| 479 | 508 |
| 480 // For a TOP_LEFT arrow, the x-offset always matches the border thickness. | 509 // For a TOP_LEFT arrow, the x-offset always matches the border thickness. |
| 481 EXPECT_EQ(border.GetArrowRect(rect).x(), border_images->border_thickness); | 510 EXPECT_EQ(border.GetArrowRect(rect).x(), border_images->border_thickness); |
| 482 border.Paint(paint_view, &canvas); | 511 border.Paint(paint_view, &canvas); |
| 483 } | 512 } |
| 484 } | 513 } |
| 485 | 514 |
| 486 } // namespace views | 515 } // namespace views |
| OLD | NEW |